11#include " encoding_binding.h"
2+ #include " encoding_singlebyte.h"
23#include " ada.h"
34#include " env-inl.h"
45#include " node_errors.h"
@@ -389,6 +390,62 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo<Value>& args) {
389390 }
390391}
391392
393+ void BindingData::DecodeSingleByte (const FunctionCallbackInfo<Value>& args) {
394+ Environment* env = Environment::GetCurrent (args);
395+
396+ CHECK_GE (args.Length (), 2 );
397+
398+ if (!(args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
399+ args[0 ]->IsArrayBufferView ())) {
400+ return node::THROW_ERR_INVALID_ARG_TYPE (
401+ env->isolate (),
402+ " The \" input\" argument must be an instance of SharedArrayBuffer, "
403+ " ArrayBuffer or ArrayBufferView." );
404+ }
405+
406+ CHECK (args[1 ]->IsInt32 ());
407+ const int encoding = args[1 ].As <v8::Int32>()->Value ();
408+ CHECK (encoding >= 0 && encoding < 29 );
409+
410+ ArrayBufferViewContents<uint8_t > buffer (args[0 ]);
411+ const uint8_t * data = buffer.data ();
412+ size_t length = buffer.length ();
413+
414+ if (length == 0 ) return args.GetReturnValue ().SetEmptyString ();
415+
416+ if (!simdutf::validate_ascii_with_errors (reinterpret_cast <const char *>(data), length).error ) {
417+ Local<Value> ret;
418+ if (StringBytes::Encode (env->isolate (), reinterpret_cast <const char *>(data), length, LATIN1).ToLocal (&ret)) {
419+ args.GetReturnValue ().Set (ret);
420+ }
421+ return ;
422+ }
423+
424+ uint16_t * dst = node::UncheckedMalloc<uint16_t >(length);
425+
426+ if (encoding == 28 ) {
427+ // x-user-defined
428+ for (size_t i = 0 ; i < length; i++) dst[i] = data[i] >= 0x80 ? data[i] + 0xf700 : data[i];
429+ } else {
430+ bool has_fatal = args[2 ]->IsTrue ();
431+
432+ const uint16_t * table = tSingleByteEncodings[encoding];
433+ for (size_t i = 0 ; i < length; i++) dst[i] = table[data[i]];
434+
435+ if (has_fatal && fSingleByteEncodings [encoding] &&
436+ simdutf::find (reinterpret_cast <char16_t *>(dst), reinterpret_cast <char16_t *>(dst) + length, 0xfffd ) != reinterpret_cast <char16_t *>(dst) + length
437+ ) {
438+ return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA (
439+ env->isolate (), " The encoded data was not valid for this encoding" );
440+ }
441+ }
442+
443+ Local<Value> ret;
444+ if (StringBytes::Raw (env->isolate (), dst, length).ToLocal (&ret)) {
445+ args.GetReturnValue ().Set (ret);
446+ }
447+ }
448+
392449void BindingData::ToASCII (const FunctionCallbackInfo<Value>& args) {
393450 Environment* env = Environment::GetCurrent (args);
394451 CHECK_GE (args.Length (), 1 );
@@ -421,6 +478,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
421478 SetMethod (isolate, target, " encodeInto" , EncodeInto);
422479 SetMethodNoSideEffect (isolate, target, " encodeUtf8String" , EncodeUtf8String);
423480 SetMethodNoSideEffect (isolate, target, " decodeUTF8" , DecodeUTF8);
481+ SetMethodNoSideEffect (isolate, target, " decodeSingleByte" , DecodeSingleByte);
424482 SetMethodNoSideEffect (isolate, target, " toASCII" , ToASCII);
425483 SetMethodNoSideEffect (isolate, target, " toUnicode" , ToUnicode);
426484}
@@ -438,6 +496,7 @@ void BindingData::RegisterTimerExternalReferences(
438496 registry->Register (EncodeInto);
439497 registry->Register (EncodeUtf8String);
440498 registry->Register (DecodeUTF8);
499+ registry->Register (DecodeSingleByte);
441500 registry->Register (ToASCII);
442501 registry->Register (ToUnicode);
443502}
0 commit comments