MCPcopy Create free account
hub / github.com/RustCrypto/utils / digest_blocks

Method digest_blocks

block-buffer/src/lib.rs:160–213  ·  view source on GitHub ↗
(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Array<u8, BS>]))

Source from the content-addressed store, hash-verified

158 /// the `compress` function, which accepts slice of blocks.
159 #[inline]
160 pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Array<u8, BS>])) {
161 let pos = self.get_pos();
162 // using `self.remaining()` for some reason
163 // prevents panic elimination
164 let rem = self.size() - pos;
165 let n = input.len();
166 // Note that checking condition `pos + n < BlockSize` is
167 // equivalent to checking `n < rem`, where `rem` is equal
168 // to `BlockSize - pos`. Using the latter allows us to work
169 // around compiler accounting for possible overflow of
170 // `pos + n` which results in it inserting unreachable
171 // panic branches. Using `unreachable_unchecked` in `get_pos`
172 // we convince compiler that `BlockSize - pos` never underflows.
173 if K::invariant(n, rem) {
174 // SAFETY: we have checked that length of `input` is smaller than
175 // number of remaining bytes in `buffer`, so we can safely write data
176 // into them and update cursor position.
177 unsafe {
178 let buf_ptr = self.buffer.as_mut_ptr().cast::<u8>().add(pos);
179 ptr::copy_nonoverlapping(input.as_ptr(), buf_ptr, input.len());
180 self.set_pos_unchecked(pos + input.len());
181 }
182 return;
183 }
184 if pos != 0 {
185 let (left, right) = input.split_at(rem);
186 input = right;
187
188 let g = ResetGuard(self);
189 let buf = &mut g.0.buffer;
190 // SAFETY: length of `left` is equal to number of remaining bytes in `buffer`,
191 // so we can copy data into it and process `buffer` as fully initialized block.
192 // Note that this code can temporarily break the eager buffer invariant,
193 // but we reset the buffer immediately after `compress` using `Drop` impl of
194 // `ResetGuard`, so this code is safe even if `compress` panics.
195 let block = unsafe {
196 let buf_ptr = buf.as_mut_ptr().cast::<u8>().add(pos);
197 ptr::copy_nonoverlapping(left.as_ptr(), buf_ptr, left.len());
198 buf.assume_init_ref()
199 };
200 compress(slice::from_ref(block));
201 }
202
203 let (blocks, leftover) = K::split_blocks(input);
204 if !blocks.is_empty() {
205 compress(blocks);
206 }
207
208 // SAFETY: `leftover` is always smaller than block size,
209 // so it satisfies the method's safety requirements for all buffer kinds
210 unsafe {
211 self.set_data_unchecked(leftover);
212 }
213 }
214
215 /// Reset buffer by setting cursor position to zero.
216 #[inline(always)]

Callers 6

test_eager_digestFunction · 0.80
test_lazy_digestFunction · 0.80
digest_pad_combinationsFunction · 0.80
test_eager_serializeFunction · 0.80
test_lazy_serializeFunction · 0.80

Calls 8

lenMethod · 0.80
split_atMethod · 0.80
is_emptyMethod · 0.80
set_data_uncheckedMethod · 0.80
ResetGuardClass · 0.70
get_posMethod · 0.45
sizeMethod · 0.45
set_pos_uncheckedMethod · 0.45

Tested by 6

test_eager_digestFunction · 0.64
test_lazy_digestFunction · 0.64
digest_pad_combinationsFunction · 0.64
test_eager_serializeFunction · 0.64
test_lazy_serializeFunction · 0.64