Skip to content

Commit 5ad6c20

Browse files
anonrigruyadorno
authored andcommitted
buffer: add isAscii method
PR-URL: #46046 Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 7aac21e commit 5ad6c20

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

doc/api/buffer.md

+14
Original file line numberDiff line numberDiff line change
@@ -5130,6 +5130,20 @@ For code running using Node.js APIs, converting between base64-encoded strings
51305130
and binary data should be performed using `Buffer.from(str, 'base64')` and
51315131
`buf.toString('base64')`.**
51325132

5133+
### `buffer.isAscii(input)`
5134+
5135+
<!-- YAML
5136+
added: REPLACEME
5137+
-->
5138+
5139+
* input {Buffer | ArrayBuffer | TypedArray} The input to validate.
5140+
* Returns: {boolean}
5141+
5142+
This function returns `true` if `input` contains only valid ASCII-encoded data,
5143+
including the case in which `input` is empty.
5144+
5145+
Throws if the `input` is a detached array buffer.
5146+
51335147
### `buffer.isUtf8(input)`
51345148

51355149
<!-- YAML

lib/buffer.js

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const {
5656
compareOffset,
5757
createFromString,
5858
fill: bindingFill,
59+
isAscii: bindingIsAscii,
5960
isUtf8: bindingIsUtf8,
6061
indexOfBuffer,
6162
indexOfNumber,
@@ -1323,11 +1324,20 @@ function isUtf8(input) {
13231324
throw new ERR_INVALID_ARG_TYPE('input', ['TypedArray', 'Buffer'], input);
13241325
}
13251326

1327+
function isAscii(input) {
1328+
if (isTypedArray(input) || isAnyArrayBuffer(input)) {
1329+
return bindingIsAscii(input);
1330+
}
1331+
1332+
throw new ERR_INVALID_ARG_TYPE('input', ['ArrayBuffer', 'Buffer', 'TypedArray'], input);
1333+
}
1334+
13261335
module.exports = {
13271336
Buffer,
13281337
SlowBuffer,
13291338
transcode,
13301339
isUtf8,
1340+
isAscii,
13311341

13321342
// Legacy
13331343
kMaxLength,

src/node_buffer.cc

+17
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,21 @@ static void IsUtf8(const FunctionCallbackInfo<Value>& args) {
12381238
args.GetReturnValue().Set(simdutf::validate_utf8(abv.data(), abv.length()));
12391239
}
12401240

1241+
static void IsAscii(const FunctionCallbackInfo<Value>& args) {
1242+
Environment* env = Environment::GetCurrent(args);
1243+
CHECK_EQ(args.Length(), 1);
1244+
CHECK(args[0]->IsTypedArray() || args[0]->IsArrayBuffer() ||
1245+
args[0]->IsSharedArrayBuffer());
1246+
ArrayBufferViewContents<char> abv(args[0]);
1247+
1248+
if (abv.WasDetached()) {
1249+
return node::THROW_ERR_INVALID_STATE(
1250+
env, "Cannot validate on a detached buffer");
1251+
}
1252+
1253+
args.GetReturnValue().Set(simdutf::validate_ascii(abv.data(), abv.length()));
1254+
}
1255+
12411256
void SetBufferPrototype(const FunctionCallbackInfo<Value>& args) {
12421257
Environment* env = Environment::GetCurrent(args);
12431258

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

13751390
SetMethodNoSideEffect(context, target, "isUtf8", IsUtf8);
1391+
SetMethodNoSideEffect(context, target, "isAscii", IsAscii);
13761392

13771393
target
13781394
->Set(context,
@@ -1430,6 +1446,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
14301446
registry->Register(EncodeUtf8String);
14311447

14321448
registry->Register(IsUtf8);
1449+
registry->Register(IsAscii);
14331450

14341451
registry->Register(StringSlice<ASCII>);
14351452
registry->Register(StringSlice<BASE64>);

test/parallel/test-buffer-isascii.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const { isAscii, Buffer } = require('buffer');
6+
const { TextEncoder } = require('util');
7+
8+
const encoder = new TextEncoder();
9+
10+
assert.strictEqual(isAscii(encoder.encode('hello')), true);
11+
assert.strictEqual(isAscii(encoder.encode('ğ')), false);
12+
assert.strictEqual(isAscii(Buffer.from([])), true);
13+
14+
[
15+
undefined,
16+
'', 'hello',
17+
false, true,
18+
0, 1,
19+
0n, 1n,
20+
Symbol(),
21+
() => {},
22+
{}, [], null,
23+
].forEach((input) => {
24+
assert.throws(
25+
() => { isAscii(input); },
26+
{
27+
code: 'ERR_INVALID_ARG_TYPE',
28+
},
29+
);
30+
});
31+
32+
{
33+
// Test with detached array buffers
34+
const arrayBuffer = new ArrayBuffer(1024);
35+
structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
36+
assert.throws(
37+
() => { isAscii(arrayBuffer); },
38+
{
39+
code: 'ERR_INVALID_STATE'
40+
}
41+
);
42+
}

0 commit comments

Comments
 (0)