11#include " encoding_binding.h"
22#include " ada.h"
3+ #include " encoding_singlebyte.h"
34#include " env-inl.h"
45#include " node_errors.h"
56#include " node_external_reference.h"
@@ -398,6 +399,73 @@ void BindingData::DecodeUTF8(const FunctionCallbackInfo<Value>& args) {
398399 }
399400}
400401
402+ void BindingData::DecodeSingleByte (const FunctionCallbackInfo<Value>& args) {
403+ Environment* env = Environment::GetCurrent (args);
404+
405+ CHECK_GE (args.Length (), 2 );
406+ Isolate* isolate = env->isolate ();
407+
408+ if (!(args[0 ]->IsArrayBuffer () || args[0 ]->IsSharedArrayBuffer () ||
409+ args[0 ]->IsArrayBufferView ())) {
410+ return node::THROW_ERR_INVALID_ARG_TYPE (
411+ isolate,
412+ " The \" input\" argument must be an instance of SharedArrayBuffer, "
413+ " ArrayBuffer or ArrayBufferView." );
414+ }
415+
416+ CHECK (args[1 ]->IsInt32 ());
417+ const int encoding = args[1 ].As <v8::Int32>()->Value ();
418+ CHECK (encoding >= 0 && encoding <= kXUserDefined );
419+
420+ ArrayBufferViewContents<uint8_t > buffer (args[0 ]);
421+ const uint8_t * data = buffer.data ();
422+ size_t length = buffer.length ();
423+
424+ if (length == 0 ) return args.GetReturnValue ().SetEmptyString ();
425+
426+ const char * dataChar = reinterpret_cast <const char *>(data);
427+ if (!simdutf::validate_ascii_with_errors (dataChar, length).error ) {
428+ Local<Value> ret;
429+ if (StringBytes::Encode (isolate, dataChar, length, LATIN1).ToLocal (&ret)) {
430+ args.GetReturnValue ().Set (ret);
431+ }
432+ return ;
433+ }
434+
435+ if (length > static_cast <size_t >(v8::String::kMaxLength )) {
436+ isolate->ThrowException (ERR_STRING_TOO_LONG (isolate));
437+ return ;
438+ }
439+
440+ uint16_t * dst = node::UncheckedMalloc<uint16_t >(length);
441+ if (dst == nullptr ) return node::THROW_ERR_MEMORY_ALLOCATION_FAILED (isolate);
442+
443+ if (encoding == kXUserDefined ) {
444+ // x-user-defined
445+ for (size_t i = 0 ; i < length; i++) {
446+ dst[i] = data[i] >= 0x80 ? data[i] + 0xf700 : data[i];
447+ }
448+ } else {
449+ bool has_fatal = args[2 ]->IsTrue ();
450+
451+ const uint16_t * table = tSingleByteEncodings[encoding];
452+ for (size_t i = 0 ; i < length; i++) dst[i] = table[data[i]];
453+
454+ const char16_t * dst16 = reinterpret_cast <char16_t *>(dst);
455+ if (has_fatal && fSingleByteEncodings [encoding] &&
456+ simdutf::find (dst16, dst16 + length, 0xfffd ) != dst16 + length) {
457+ free (dst);
458+ return node::THROW_ERR_ENCODING_INVALID_ENCODED_DATA (
459+ isolate, " The encoded data was not valid for this encoding" );
460+ }
461+ }
462+
463+ Local<Value> ret;
464+ if (StringBytes::Raw (isolate, dst, length).ToLocal (&ret)) {
465+ args.GetReturnValue ().Set (ret);
466+ }
467+ }
468+
401469void BindingData::ToASCII (const FunctionCallbackInfo<Value>& args) {
402470 Environment* env = Environment::GetCurrent (args);
403471 CHECK_GE (args.Length (), 1 );
@@ -430,6 +498,7 @@ void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
430498 SetMethod (isolate, target, " encodeInto" , EncodeInto);
431499 SetMethodNoSideEffect (isolate, target, " encodeUtf8String" , EncodeUtf8String);
432500 SetMethodNoSideEffect (isolate, target, " decodeUTF8" , DecodeUTF8);
501+ SetMethodNoSideEffect (isolate, target, " decodeSingleByte" , DecodeSingleByte);
433502 SetMethodNoSideEffect (isolate, target, " toASCII" , ToASCII);
434503 SetMethodNoSideEffect (isolate, target, " toUnicode" , ToUnicode);
435504}
@@ -447,6 +516,7 @@ void BindingData::RegisterTimerExternalReferences(
447516 registry->Register (EncodeInto);
448517 registry->Register (EncodeUtf8String);
449518 registry->Register (DecodeUTF8);
519+ registry->Register (DecodeSingleByte);
450520 registry->Register (ToASCII);
451521 registry->Register (ToUnicode);
452522}
0 commit comments