File tree Expand file tree Collapse file tree
portability/no_alloc_smoke/src Expand file tree Collapse file tree Original file line number Diff line number Diff line change 7676 unwrapped ` Profile ` .
7777- Added ` ct::CtEngine::decoded_len() ` so sensitive decode paths can size
7878 caller-owned buffers without switching to the diagnostic decoder.
79+ - Added ` Engine::ct_decoder() ` for explicit promotion to the matching
80+ constant-time-oriented decoder without type annotations.
7981
8082## 0.8.0 - 2026-05-16
8183
Original file line number Diff line number Diff line change @@ -248,15 +248,18 @@ assert!(MIME.validate(&encoded[..written]));
248248```
249249
250250An engine can also be promoted explicitly to an unwrapped profile when a common
251- configuration path expects profile values:
251+ configuration path expects profile values, or to the matching
252+ constant-time-oriented decoder when sensitive decode policy is required:
252253
253254``` rust
254255use base64_ng :: STANDARD ;
255256
256257let profile = STANDARD . profile ();
258+ let ct_decoder = STANDARD . ct_decoder ();
257259
258260assert! (profile . is_padded ());
259261assert! (! profile . is_wrapped ());
262+ assert_eq! (ct_decoder . decoded_len (b " aGVsbG8=" ). unwrap (), 5 );
260263```
261264
262265When wrapping policy comes from configuration, prefer checked construction:
Original file line number Diff line number Diff line change @@ -159,6 +159,9 @@ pub fn custom_profile_surfaces() -> bool {
159159 {
160160 return false ;
161161 }
162+ if STANDARD . ct_decoder ( ) . decoded_len ( b"aGVsbG8=" ) != Ok ( 5 ) {
163+ return false ;
164+ }
162165
163166 let encoded = match SMOKE_NO_PAD . encode_buffer :: < 4 > ( & [ 0xff , 0xff , 0xff ] ) {
164167 Ok ( encoded) => encoded,
Original file line number Diff line number Diff line change @@ -3928,6 +3928,16 @@ where
39283928 Profile :: new ( * self , None )
39293929 }
39303930
3931+ /// Returns the matching constant-time-oriented decoder for this engine's
3932+ /// alphabet and padding policy.
3933+ ///
3934+ /// The returned decoder is still an explicit opt-in to the [`ct`] module's
3935+ /// slower, opaque-error, constant-time-oriented scalar path.
3936+ #[ must_use]
3937+ pub const fn ct_decoder ( & self ) -> ct:: CtEngine < A , PAD > {
3938+ ct:: CtEngine :: new ( )
3939+ }
3940+
39313941 /// Returns the encoded length for this engine's padding policy.
39323942 pub const fn encoded_len ( & self , input_len : usize ) -> Result < usize , EncodeError > {
39333943 encoded_len ( input_len, PAD )
Original file line number Diff line number Diff line change @@ -254,6 +254,10 @@ fn named_profiles_expose_expected_policies() {
254254 assert_eq ! ( URL_SAFE_NO_PAD . profile( ) . engine( ) , URL_SAFE_NO_PAD ) ;
255255 assert ! ( !URL_SAFE_NO_PAD . profile( ) . is_padded( ) ) ;
256256 assert ! ( !URL_SAFE_NO_PAD . profile( ) . is_wrapped( ) ) ;
257+ assert_eq ! ( STANDARD . ct_decoder( ) , ct:: STANDARD ) ;
258+ assert_eq ! ( STANDARD_NO_PAD . ct_decoder( ) , ct:: STANDARD_NO_PAD ) ;
259+ assert_eq ! ( URL_SAFE . ct_decoder( ) , ct:: URL_SAFE ) ;
260+ assert_eq ! ( URL_SAFE_NO_PAD . ct_decoder( ) , ct:: URL_SAFE_NO_PAD ) ;
257261 assert ! ( standard_profile. is_padded( ) ) ;
258262 assert ! ( !standard_profile. is_wrapped( ) ) ;
259263 assert ! ( standard_profile. is_valid( ) ) ;
You can’t perform that action at this time.
0 commit comments