Skip to content

Commit

Permalink
buffer: add isAscii method
Browse files Browse the repository at this point in the history
PR-URL: #46046
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
  • Loading branch information
anonrig authored and juanarbol committed Mar 5, 2023
1 parent 75b8db4 commit cb5bb12
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 0 deletions.
14 changes: 14 additions & 0 deletions doc/api/buffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -5126,6 +5126,20 @@ For code running using Node.js APIs, converting between base64-encoded strings
and binary data should be performed using `Buffer.from(str, 'base64')` and
`buf.toString('base64')`.**

### `buffer.isAscii(input)`

<!-- YAML
added: REPLACEME
-->

* input {Buffer | ArrayBuffer | TypedArray} The input to validate.
* Returns: {boolean}

This function returns `true` if `input` contains only valid ASCII-encoded data,
including the case in which `input` is empty.

Throws if the `input` is a detached array buffer.

### `buffer.isUtf8(input)`

<!-- YAML
Expand Down
10 changes: 10 additions & 0 deletions lib/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const {
compareOffset,
createFromString,
fill: bindingFill,
isAscii: bindingIsAscii,
isUtf8: bindingIsUtf8,
indexOfBuffer,
indexOfNumber,
Expand Down Expand Up @@ -1332,6 +1333,14 @@ function isUtf8(input) {
throw new ERR_INVALID_ARG_TYPE('input', ['TypedArray', 'Buffer'], input);
}

function isAscii(input) {
if (isTypedArray(input) || isAnyArrayBuffer(input)) {
return bindingIsAscii(input);
}

throw new ERR_INVALID_ARG_TYPE('input', ['ArrayBuffer', 'Buffer', 'TypedArray'], input);
}

module.exports = {
Blob,
File,
Expand All @@ -1340,6 +1349,7 @@ module.exports = {
SlowBuffer,
transcode,
isUtf8,
isAscii,

// Legacy
kMaxLength,
Expand Down
17 changes: 17 additions & 0 deletions src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1238,6 +1238,21 @@ static void IsUtf8(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(simdutf::validate_utf8(abv.data(), abv.length()));
}

static void IsAscii(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
CHECK_EQ(args.Length(), 1);
CHECK(args[0]->IsTypedArray() || args[0]->IsArrayBuffer() ||
args[0]->IsSharedArrayBuffer());
ArrayBufferViewContents<char> abv(args[0]);

if (abv.WasDetached()) {
return node::THROW_ERR_INVALID_STATE(
env, "Cannot validate on a detached buffer");
}

args.GetReturnValue().Set(simdutf::validate_ascii(abv.data(), abv.length()));
}

void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

Expand Down Expand Up @@ -1373,6 +1388,7 @@ void Initialize(Local<Object> target,
SetMethodNoSideEffect(context, target, "encodeUtf8String", EncodeUtf8String);

SetMethodNoSideEffect(context, target, "isUtf8", IsUtf8);
SetMethodNoSideEffect(context, target, "isAscii", IsAscii);

target
->Set(context,
Expand Down Expand Up @@ -1430,6 +1446,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
registry->Register(EncodeUtf8String);

registry->Register(IsUtf8);
registry->Register(IsAscii);

registry->Register(StringSlice<ASCII>);
registry->Register(StringSlice<BASE64>);
Expand Down
42 changes: 42 additions & 0 deletions test/parallel/test-buffer-isascii.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use strict';

require('../common');
const assert = require('assert');
const { isAscii, Buffer } = require('buffer');
const { TextEncoder } = require('util');

const encoder = new TextEncoder();

assert.strictEqual(isAscii(encoder.encode('hello')), true);
assert.strictEqual(isAscii(encoder.encode('ğ')), false);
assert.strictEqual(isAscii(Buffer.from([])), true);

[
undefined,
'', 'hello',
false, true,
0, 1,
0n, 1n,
Symbol(),
() => {},
{}, [], null,
].forEach((input) => {
assert.throws(
() => { isAscii(input); },
{
code: 'ERR_INVALID_ARG_TYPE',
},
);
});

{
// Test with detached array buffers
const arrayBuffer = new ArrayBuffer(1024);
structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
assert.throws(
() => { isAscii(arrayBuffer); },
{
code: 'ERR_INVALID_STATE'
}
);
}

0 comments on commit cb5bb12

Please sign in to comment.