@@ -48,21 +48,18 @@ pub trait Padding {
4848
4949 /// Pad message and return padded tail block.
5050 ///
51- /// `Err` is returned only by [`NoPadding`] if `data` length is not multiple of the block size.
52- /// [`NoPadding`] and [`ZeroPadding`] return `Ok((blocks, None))` if `data` length
53- /// is multiple of block size. All other padding implementations should always return
54- /// `Ok((blocks, Some(tail_block)))`.
55- #[ allow( clippy:: type_complexity) ]
51+ /// [`PaddedData::Error`] is returned only by [`NoPadding`] if `data` length is not multiple
52+ /// of the block size. [`NoPadding`] and [`ZeroPadding`] return [`PaddedData::NoPad`]
53+ /// if `data` length is multiple of block size. All other padding implementations
54+ /// should always return [`PaddedData::Pad`].
5655 #[ inline]
57- fn pad_detached < BlockSize : ArraySize > (
58- data : & [ u8 ] ,
59- ) -> Result < ( & [ Array < u8 , BlockSize > ] , Option < Array < u8 , BlockSize > > ) , Error > {
56+ fn pad_detached < BlockSize : ArraySize > ( data : & [ u8 ] ) -> PaddedData < ' _ , BlockSize > {
6057 let ( blocks, tail) = Array :: slice_as_chunks ( data) ;
6158 let mut tail_block = Array :: default ( ) ;
6259 let pos = tail. len ( ) ;
6360 tail_block[ ..pos] . copy_from_slice ( tail) ;
6461 Self :: pad ( & mut tail_block, pos) ;
65- Ok ( ( blocks, Some ( tail_block) ) )
62+ PaddedData :: Pad { blocks, tail_block }
6663 }
6764
6865 /// Unpad data in `blocks` and return unpadded byte slice.
@@ -120,6 +117,19 @@ impl Padding for ZeroPadding {
120117 Ok ( & block[ ..0 ] )
121118 }
122119
120+ #[ inline]
121+ fn pad_detached < BlockSize : ArraySize > ( data : & [ u8 ] ) -> PaddedData < ' _ , BlockSize > {
122+ let ( blocks, tail) = Array :: slice_as_chunks ( data) ;
123+ if tail. is_empty ( ) {
124+ return PaddedData :: NoPad { blocks } ;
125+ }
126+ let mut tail_block = Array :: default ( ) ;
127+ let pos = tail. len ( ) ;
128+ tail_block[ ..pos] . copy_from_slice ( tail) ;
129+ Self :: pad ( & mut tail_block, pos) ;
130+ PaddedData :: Pad { blocks, tail_block }
131+ }
132+
123133 #[ inline]
124134 fn unpad_blocks < BlockSize : ArraySize > ( blocks : & [ Array < u8 , BlockSize > ] ) -> Result < & [ u8 ] , Error > {
125135 let buf = Array :: slice_as_flattened ( blocks) ;
@@ -353,6 +363,16 @@ impl Padding for NoPadding {
353363 Ok ( block)
354364 }
355365
366+ #[ inline]
367+ fn pad_detached < BlockSize : ArraySize > ( data : & [ u8 ] ) -> PaddedData < ' _ , BlockSize > {
368+ let ( blocks, tail) = Array :: slice_as_chunks ( data) ;
369+ if tail. is_empty ( ) {
370+ PaddedData :: NoPad { blocks }
371+ } else {
372+ PaddedData :: Error
373+ }
374+ }
375+
356376 #[ inline]
357377 fn unpad_blocks < BlockSize : ArraySize > ( blocks : & [ Array < u8 , BlockSize > ] ) -> Result < & [ u8 ] , Error > {
358378 Ok ( Array :: slice_as_flattened ( blocks) )
@@ -370,3 +390,37 @@ impl fmt::Display for Error {
370390}
371391
372392impl core:: error:: Error for Error { }
393+
394+ /// Padded data split into blocks with detached last block returned by [`Padding::pad_detached`].
395+ #[ derive( Debug ) ]
396+ pub enum PaddedData < ' a , BlockSize : ArraySize > {
397+ /// Message split into blocks with detached and padded `tail_block`.
398+ Pad {
399+ /// Message blocks.
400+ blocks : & ' a [ Array < u8 , BlockSize > ] ,
401+ /// Last message block with padding.
402+ tail_block : Array < u8 , BlockSize > ,
403+ } ,
404+ /// [`NoPadding`] or [`ZeroPadding`] were used on a message which does not require any padding.
405+ NoPad {
406+ /// Message blocks.
407+ blocks : & ' a [ Array < u8 , BlockSize > ] ,
408+ } ,
409+ /// [`NoPadding`] was used on a message with size not multiple of the block size.
410+ Error ,
411+ }
412+
413+ impl < ' a , BlockSize : ArraySize > PaddedData < ' a , BlockSize > {
414+ /// Unwrap the `Pad` variant.
415+ pub fn unwrap ( self ) -> ( & ' a [ Array < u8 , BlockSize > ] , Array < u8 , BlockSize > ) {
416+ match self {
417+ PaddedData :: Pad { blocks, tail_block } => ( blocks, tail_block) ,
418+ PaddedData :: NoPad { .. } => {
419+ panic ! ( "Expected `PaddedData::Pad`, but got `PaddedData::NoPad`" ) ;
420+ }
421+ PaddedData :: Error => {
422+ panic ! ( "Expected `PaddedData::Pad`, but got `PaddedData::Error`" ) ;
423+ }
424+ }
425+ }
426+ }
0 commit comments