11#include " encoding_binding.h"
2+ #include " encoding_singlebyte.h"
23#include " ada.h"
34#include " env-inl.h"
45#include " node_errors.h"
@@ -379,6 +380,66 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo<Value>& args) {
379380 }
380381}
381382
383+ void BindingData::DecodeSingleByte (const FunctionCallbackInfo<Value>& args) {
384+ Environment* env = Environment::GetCurrent (args);
385+
386+ CHECK_GE (args.Length (), 2 );
387+
388+ if (!(args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
389+ args[0 ]->IsArrayBufferView ())) {
390+ return node::THROW_ERR_INVALID_ARG_TYPE (
391+ env->isolate (),
392+ " The \" list\" argument must be an instance of SharedArrayBuffer, "
393+ " ArrayBuffer or ArrayBufferView." );
394+ }
395+
396+ CHECK (args[1 ]->IsInt32 ());
397+ const int encoding = args[1 ].As <v8::Int32>()->Value ();
398+ CHECK (encoding >= 0 && encoding < 29 );
399+
400+ ArrayBufferViewContents<uint8_t > buffer (args[0 ]);
401+ const uint8_t * data = buffer.data ();
402+ size_t length = buffer.length ();
403+
404+ if (length == 0 ) return args.GetReturnValue ().SetEmptyString ();
405+
406+ if (simdutf::validate_ascii (reinterpret_cast <const char *>(data), length)) {
407+ Local<Value> ret;
408+ if (StringBytes::Encode (env->isolate (), reinterpret_cast <const char *>(data), length, LATIN1).ToLocal (&ret)) {
409+ args.GetReturnValue ().Set (ret);
410+ }
411+ return ;
412+ }
413+
414+ uint16_t * dst = node::UncheckedMalloc<uint16_t >(length);
415+
416+ if (encoding == 28 ) {
417+ // x-user-defined
418+ for (size_t i = 0 ; i < length; i++) dst[i] = data[i] >= 0x80 ? data[i] + 0xf700 : data[i];
419+ } else {
420+ bool has_fatal = args[2 ]->IsTrue ();
421+
422+ // TODO: make this static
423+ uint16_t table[256 ] = { 0 };
424+ for (size_t i = 0 ; i < 128 ; i++) table[i] = i;
425+ memcpy (table + 128 , tSingleByteEncodings[encoding], 256 );
426+
427+ for (size_t i = 0 ; i < length; i++) dst[i] = table[data[i]];
428+
429+ if (has_fatal && fSingleByteEncodings [encoding] &&
430+ simdutf::find (reinterpret_cast <char16_t *>(dst), reinterpret_cast <char16_t *>(dst) + length, 0xfffd ) != reinterpret_cast <char16_t *>(dst) + length
431+ ) {
432+ return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA (
433+ env->isolate (), " The encoded data was not valid for this encoding" );
434+ }
435+ }
436+
437+ Local<Value> ret;
438+ if (StringBytes::Raw (env->isolate (), dst, length).ToLocal (&ret)) {
439+ args.GetReturnValue ().Set (ret);
440+ }
441+ }
442+
382443void BindingData::ToASCII (const FunctionCallbackInfo<Value>& args) {
383444 Environment* env = Environment::GetCurrent (args);
384445 CHECK_GE (args.Length (), 1 );
@@ -411,6 +472,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
411472 SetMethod (isolate, target, " encodeInto" , EncodeInto);
412473 SetMethodNoSideEffect (isolate, target, " encodeUtf8String" , EncodeUtf8String);
413474 SetMethodNoSideEffect (isolate, target, " decodeUTF8" , DecodeUTF8);
475+ SetMethodNoSideEffect (isolate, target, " decodeSingleByte" , DecodeSingleByte);
414476 SetMethodNoSideEffect (isolate, target, " toASCII" , ToASCII);
415477 SetMethodNoSideEffect (isolate, target, " toUnicode" , ToUnicode);
416478}
@@ -428,6 +490,7 @@ void BindingData::RegisterTimerExternalReferences(
428490 registry->Register (EncodeInto);
429491 registry->Register (EncodeUtf8String);
430492 registry->Register (DecodeUTF8);
493+ registry->Register (DecodeSingleByte);
431494 registry->Register (ToASCII);
432495 registry->Register (ToUnicode);
433496}
0 commit comments