@@ -346,17 +346,113 @@ size_t StringBytes::Write(Isolate* isolate,
346346 }
347347
348348 case BASE64URL:
349- // Fall through
350- case BASE64:
351- if (str->IsExternalOneByte ()) {
349+ if (str->IsExternalOneByte ()) { // 8-bit case
352350 auto ext = str->GetExternalOneByteStringResource ();
353- nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
351+ size_t written_len = buflen;
352+ auto result = simdutf::base64_to_binary_safe (
353+ ext->data (), ext->length (), buf, written_len, simdutf::base64_url);
354+ if (result.error == simdutf::error_code::SUCCESS) {
355+ nbytes = written_len;
356+ } else {
357+ // The input does not follow the WHATWG forgiving-base64 specification
358+ // adapted for base64url
359+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
360+ nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
361+ }
362+ } else if (str->IsOneByte ()) {
363+ MaybeStackBuffer<uint8_t > stack_buf (str->Length ());
364+ str->WriteOneByte (isolate,
365+ stack_buf.out (),
366+ 0 ,
367+ str->Length (),
368+ String::NO_NULL_TERMINATION);
369+ size_t written_len = buflen;
370+ auto result = simdutf::base64_to_binary_safe (
371+ reinterpret_cast <const char *>(*stack_buf),
372+ stack_buf.length (),
373+ buf,
374+ written_len,
375+ simdutf::base64_url);
376+ if (result.error == simdutf::error_code::SUCCESS) {
377+ nbytes = written_len;
378+ } else {
379+ // The input does not follow the WHATWG forgiving-base64 specification
380+ // (adapted for base64url with + and / replaced by - and _).
381+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
382+ nbytes = base64_decode (buf, buflen, *stack_buf, stack_buf.length ());
383+ }
354384 } else {
355385 String::Value value (isolate, str);
356- nbytes = base64_decode (buf, buflen, *value, value.length ());
386+ size_t written_len = buflen;
387+ auto result = simdutf::base64_to_binary_safe (
388+ reinterpret_cast <const char16_t *>(*value),
389+ value.length (),
390+ buf,
391+ written_len,
392+ simdutf::base64_url);
393+ if (result.error == simdutf::error_code::SUCCESS) {
394+ nbytes = written_len;
395+ } else {
396+ // The input does not follow the WHATWG forgiving-base64 specification
397+ // (adapted for base64url with + and / replaced by - and _).
398+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
399+ nbytes = base64_decode (buf, buflen, *value, value.length ());
400+ }
357401 }
358402 break ;
359403
404+ case BASE64: {
405+ if (str->IsExternalOneByte ()) { // 8-bit case
406+ auto ext = str->GetExternalOneByteStringResource ();
407+ size_t written_len = buflen;
408+ auto result = simdutf::base64_to_binary_safe (
409+ ext->data (), ext->length (), buf, written_len);
410+ if (result.error == simdutf::error_code::SUCCESS) {
411+ nbytes = written_len;
412+ } else {
413+ // The input does not follow the WHATWG forgiving-base64 specification
414+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
415+ nbytes = base64_decode (buf, buflen, ext->data (), ext->length ());
416+ }
417+ } else if (str->IsOneByte ()) {
418+ MaybeStackBuffer<uint8_t > stack_buf (str->Length ());
419+ str->WriteOneByte (isolate,
420+ stack_buf.out (),
421+ 0 ,
422+ str->Length (),
423+ String::NO_NULL_TERMINATION);
424+ size_t written_len = buflen;
425+ auto result = simdutf::base64_to_binary_safe (
426+ reinterpret_cast <const char *>(*stack_buf),
427+ stack_buf.length (),
428+ buf,
429+ written_len);
430+ if (result.error == simdutf::error_code::SUCCESS) {
431+ nbytes = written_len;
432+ } else {
433+ // The input does not follow the WHATWG forgiving-base64 specification
434+ // (adapted for base64url with + and / replaced by - and _).
435+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
436+ nbytes = base64_decode (buf, buflen, *stack_buf, stack_buf.length ());
437+ }
438+ } else {
439+ String::Value value (isolate, str);
440+ size_t written_len = buflen;
441+ auto result = simdutf::base64_to_binary_safe (
442+ reinterpret_cast <const char16_t *>(*value),
443+ value.length (),
444+ buf,
445+ written_len);
446+ if (result.error == simdutf::error_code::SUCCESS) {
447+ nbytes = written_len;
448+ } else {
449+ // The input does not follow the WHATWG base64 specification
450+ // https://infra.spec.whatwg.org/#forgiving-base64-decode
451+ nbytes = base64_decode (buf, buflen, *value, value.length ());
452+ }
453+ }
454+ break ;
455+ }
360456 case HEX:
361457 if (str->IsExternalOneByte ()) {
362458 auto ext = str->GetExternalOneByteStringResource ();
@@ -411,9 +507,12 @@ Maybe<size_t> StringBytes::StorageSize(Isolate* isolate,
411507 break ;
412508
413509 case BASE64URL:
414- // Fall through
510+ data_size = simdutf::base64_length_from_binary (str->Length (),
511+ simdutf::base64_url);
512+ break ;
513+
415514 case BASE64:
416- data_size = base64_decoded_size_fast (str->Length ());
515+ data_size = simdutf::base64_length_from_binary (str->Length ());
417516 break ;
418517
419518 case HEX:
@@ -452,11 +551,15 @@ Maybe<size_t> StringBytes::Size(Isolate* isolate,
452551 case UCS2:
453552 return Just (str->Length () * sizeof (uint16_t ));
454553
455- case BASE64URL:
456- // Fall through
554+ case BASE64URL: {
555+ String::Value value (isolate, str);
556+ return Just (simdutf::base64_length_from_binary (value.length (),
557+ simdutf::base64_url));
558+ }
559+
457560 case BASE64: {
458561 String::Value value (isolate, str);
459- return Just (base64_decoded_size (*value, value.length ()));
562+ return Just (simdutf::base64_length_from_binary ( value.length ()));
460563 }
461564
462565 case HEX:
@@ -609,28 +712,30 @@ MaybeLocal<Value> StringBytes::Encode(Isolate* isolate,
609712 return ExternOneByteString::NewFromCopy (isolate, buf, buflen, error);
610713
611714 case BASE64: {
612- size_t dlen = base64_encoded_size (buflen);
715+ size_t dlen = simdutf::base64_length_from_binary (buflen);
613716 char * dst = node::UncheckedMalloc (dlen);
614717 if (dst == nullptr ) {
615718 *error = node::ERR_MEMORY_ALLOCATION_FAILED (isolate);
616719 return MaybeLocal<Value>();
617720 }
618721
619- size_t written = base64_encode (buf, buflen, dst, dlen );
722+ size_t written = simdutf::binary_to_base64 (buf, buflen, dst);
620723 CHECK_EQ (written, dlen);
621724
622725 return ExternOneByteString::New (isolate, dst, dlen, error);
623726 }
624727
625728 case BASE64URL: {
626- size_t dlen = base64_encoded_size (buflen, Base64Mode::URL);
729+ size_t dlen =
730+ simdutf::base64_length_from_binary (buflen, simdutf::base64_url);
627731 char * dst = node::UncheckedMalloc (dlen);
628732 if (dst == nullptr ) {
629733 *error = node::ERR_MEMORY_ALLOCATION_FAILED (isolate);
630734 return MaybeLocal<Value>();
631735 }
632736
633- size_t written = base64_encode (buf, buflen, dst, dlen, Base64Mode::URL);
737+ size_t written =
738+ simdutf::binary_to_base64 (buf, buflen, dst, simdutf::base64_url);
634739 CHECK_EQ (written, dlen);
635740
636741 return ExternOneByteString::New (isolate, dst, dlen, error);
0 commit comments