@@ -8,6 +8,7 @@ use byteorder::{ByteOrder, BE};
8
8
use byte_tools:: zero;
9
9
use block_padding:: { Padding , PadError } ;
10
10
use generic_array:: { GenericArray , ArrayLength } ;
11
+ use core:: slice;
11
12
12
13
/// Buffer for block processing of data
13
14
#[ derive( Clone , Default ) ]
@@ -22,6 +23,8 @@ unsafe fn cast<N: ArrayLength<u8>>(block: &[u8]) -> &GenericArray<u8, N> {
22
23
& * ( block. as_ptr ( ) as * const GenericArray < u8 , N > )
23
24
}
24
25
26
+
27
+
25
28
impl < BlockSize : ArrayLength < u8 > > BlockBuffer < BlockSize > {
26
29
/// Process data in `input` in blocks of size `BlockSize` using function `f`.
27
30
#[ inline]
@@ -52,6 +55,41 @@ impl<BlockSize: ArrayLength<u8>> BlockBuffer<BlockSize> {
52
55
self . pos += input. len ( ) ;
53
56
}
54
57
58
+ /// Process data in `input` in blocks of size `BlockSize` using function `f`, which accepts
59
+ /// slice of blocks.
60
+ #[ inline]
61
+ pub fn input2 < F > ( & mut self , mut input : & [ u8 ] , mut f : F )
62
+ where F : FnMut ( & [ GenericArray < u8 , BlockSize > ] )
63
+ {
64
+ // If there is already data in the buffer, process it if we have
65
+ // enough to complete the chunk.
66
+ let rem = self . remaining ( ) ;
67
+ if self . pos != 0 && input. len ( ) >= rem {
68
+ let ( l, r) = input. split_at ( rem) ;
69
+ input = r;
70
+ self . buffer [ self . pos ..] . copy_from_slice ( l) ;
71
+ self . pos = 0 ;
72
+ f ( slice:: from_ref ( & self . buffer ) ) ;
73
+ }
74
+
75
+ // While we have at least a full buffer size chunks's worth of data,
76
+ // process it data without copying into the buffer
77
+ let n_blocks = input. len ( ) /self . size ( ) ;
78
+ let ( left, right) = input. split_at ( n_blocks* self . size ( ) ) ;
79
+ // safe because we guarantee that `blocks` does not point outside of `input`
80
+ let blocks = unsafe {
81
+ slice:: from_raw_parts (
82
+ left. as_ptr ( ) as * const GenericArray < u8 , BlockSize > ,
83
+ n_blocks,
84
+ )
85
+ } ;
86
+ f ( blocks) ;
87
+
88
+ // Copy remaining data into the buffer.
89
+ self . buffer [ self . pos ..self . pos +right. len ( ) ] . copy_from_slice ( right) ;
90
+ self . pos += right. len ( ) ;
91
+ }
92
+
55
93
/// Variant that doesn't flush the buffer until there's additional
56
94
/// data to be processed. Suitable for tweakable block ciphers
57
95
/// like Threefish that need to know whether a block is the *last*
0 commit comments