@@ -124,74 +124,41 @@ pub fn init<P: TimersPermission + 'static>(
124
124
125
125
#[ op]
126
126
fn 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 ( ) )
130
128
}
131
129
132
130
#[ 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 ( ) )
144
133
}
145
134
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" ) ;
155
139
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 ( ) ) ?;
177
142
178
- Ok ( out)
143
+ let decoded_len = decoded. len ( ) ;
144
+ input. truncate ( decoded_len) ;
145
+ Ok ( input)
179
146
}
180
147
181
148
#[ op]
182
149
fn op_base64_encode ( s : ZeroCopyBuf ) -> String {
183
- b64_encode ( & s )
150
+ forgiving_base64_encode ( s . as_ref ( ) )
184
151
}
185
152
186
153
#[ op]
187
154
fn op_base64_btoa ( s : ByteString ) -> String {
188
- b64_encode ( s )
155
+ forgiving_base64_encode ( s . as_ref ( ) )
189
156
}
190
157
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 ( )
195
162
}
196
163
197
164
#[ derive( Deserialize ) ]
0 commit comments