@@ -124,74 +124,41 @@ pub fn init<P: TimersPermission + 'static>(
124124
125125#[ op]
126126fn op_base64_decode ( input : String ) -> Result < ZeroCopyBuf , AnyError > {
127- let mut input = input. into_bytes ( ) ;
128- input. retain ( |c| !c. is_ascii_whitespace ( ) ) ;
129- Ok ( b64_decode ( & input) ?. into ( ) )
127+ Ok ( forgiving_base64_decode ( input. into_bytes ( ) ) ?. into ( ) )
130128}
131129
132130#[ op]
133- fn op_base64_atob ( mut s : ByteString ) -> Result < ByteString , AnyError > {
134- s. retain ( |c| !c. is_ascii_whitespace ( ) ) ;
135-
136- // If padding is expected, fail if not 4-byte aligned
137- if s. len ( ) % 4 != 0 && ( s. ends_with ( b"==" ) || s. ends_with ( b"=" ) ) {
138- return Err (
139- DomExceptionInvalidCharacterError :: new ( "Failed to decode base64." ) . into ( ) ,
140- ) ;
141- }
142-
143- Ok ( b64_decode ( & s) ?. into ( ) )
131+ fn op_base64_atob ( s : ByteString ) -> Result < ByteString , AnyError > {
132+ Ok ( forgiving_base64_decode ( s. into ( ) ) ?. into ( ) )
144133}
145134
146- fn b64_decode ( input : & [ u8 ] ) -> Result < Vec < u8 > , AnyError > {
147- // "If the length of input divides by 4 leaving no remainder, then:
148- // if input ends with one or two U+003D EQUALS SIGN (=) characters,
149- // remove them from input."
150- let input = match input. len ( ) % 4 == 0 {
151- true if input. ends_with ( b"==" ) => & input[ ..input. len ( ) - 2 ] ,
152- true if input. ends_with ( b"=" ) => & input[ ..input. len ( ) - 1 ] ,
153- _ => input,
154- } ;
135+ /// See <https://infra.spec.whatwg.org/#forgiving-base64>
136+ fn forgiving_base64_decode ( mut input : Vec < u8 > ) -> Result < Vec < u8 > , AnyError > {
137+ let error: _ =
138+ || DomExceptionInvalidCharacterError :: new ( "Failed to decode base64" ) ;
155139
156- // "If the length of input divides by 4 leaving a remainder of 1,
157- // throw an InvalidCharacterError exception and abort these steps."
158- if input. len ( ) % 4 == 1 {
159- return Err (
160- DomExceptionInvalidCharacterError :: new ( "Failed to decode base64." ) . into ( ) ,
161- ) ;
162- }
163-
164- let cfg = base64:: Config :: new ( base64:: CharacterSet :: Standard , true )
165- . decode_allow_trailing_bits ( true ) ;
166- let out = base64:: decode_config ( input, cfg) . map_err ( |err| match err {
167- base64:: DecodeError :: InvalidByte ( _, _) => {
168- DomExceptionInvalidCharacterError :: new (
169- "Failed to decode base64: invalid character" ,
170- )
171- }
172- _ => DomExceptionInvalidCharacterError :: new ( & format ! (
173- "Failed to decode base64: {:?}" ,
174- err
175- ) ) ,
176- } ) ?;
140+ let decoded = base64_simd:: Base64 :: forgiving_decode_inplace ( & mut input)
141+ . map_err ( |_| error ( ) ) ?;
177142
178- Ok ( out)
143+ let decoded_len = decoded. len ( ) ;
144+ input. truncate ( decoded_len) ;
145+ Ok ( input)
179146}
180147
181148#[ op]
182149fn op_base64_encode ( s : ZeroCopyBuf ) -> String {
183- b64_encode ( & s )
150+ forgiving_base64_encode ( s . as_ref ( ) )
184151}
185152
186153#[ op]
187154fn op_base64_btoa ( s : ByteString ) -> String {
188- b64_encode ( s )
155+ forgiving_base64_encode ( s . as_ref ( ) )
189156}
190157
191- fn b64_encode ( s : impl AsRef < [ u8 ] > ) -> String {
192- let cfg = base64 :: Config :: new ( base64 :: CharacterSet :: Standard , true )
193- . decode_allow_trailing_bits ( true ) ;
194- base64:: encode_config ( s . as_ref ( ) , cfg )
158+ /// See <https://infra.spec.whatwg.org/#forgiving-base64>
159+ fn forgiving_base64_encode ( s : & [ u8 ] ) -> String {
160+ let base64 = base64_simd :: Base64 :: STANDARD ;
161+ base64. encode_to_boxed_str ( s ) . into_string ( )
195162}
196163
197164#[ derive( Deserialize ) ]
0 commit comments