1use super::{ArrayLength, Block};
2use core::slice;
3
4/// Sealed trait for buffer kinds.
5pub trait Sealed {
6 /// Invariant guaranteed by a buffer kind, i.e. with correct
7 /// buffer code this function always returns true.
8 fn invariant(pos: usize, block_size: usize) -> bool;
9
10 /// Split input data into slice of blocks and tail.
11 fn split_blocks<N: ArrayLength<u8>>(data: &[u8]) -> (&[Block<N>], &[u8]);
12}
13
14impl Sealed for super::Eager {
15 #[inline(always)]
16 fn invariant(pos: usize, block_size: usize) -> bool {
17 pos < block_size
18 }
19
20 #[inline(always)]
21 fn split_blocks<N: ArrayLength<u8>>(data: &[u8]) -> (&[Block<N>], &[u8]) {
22 let nb: usize = data.len() / N::USIZE;
23 let blocks_len: usize = nb * N::USIZE;
24 let tail_len: usize = data.len() - blocks_len;
25 // SAFETY: we guarantee that created slices do not point
26 // outside of `data`
27 unsafe {
28 let blocks_ptr: *const GenericArray = data.as_ptr() as *const Block<N>;
29 let tail_ptr: *const u8 = data.as_ptr().add(count:blocks_len);
30 (
31 slice::from_raw_parts(data:blocks_ptr, len:nb),
32 slice::from_raw_parts(data:tail_ptr, tail_len),
33 )
34 }
35 }
36}
37
38impl Sealed for super::Lazy {
39 #[inline(always)]
40 fn invariant(pos: usize, block_size: usize) -> bool {
41 pos <= block_size
42 }
43
44 #[inline(always)]
45 fn split_blocks<N: ArrayLength<u8>>(data: &[u8]) -> (&[Block<N>], &[u8]) {
46 if data.is_empty() {
47 return (&[], &[]);
48 }
49 let (nb, tail_len) = if data.len() % N::USIZE == 0 {
50 (data.len() / N::USIZE - 1, N::USIZE)
51 } else {
52 let nb = data.len() / N::USIZE;
53 (nb, data.len() - nb * N::USIZE)
54 };
55 let blocks_len = nb * N::USIZE;
56 // SAFETY: we guarantee that created slices do not point
57 // outside of `data`
58 unsafe {
59 let blocks_ptr = data.as_ptr() as *const Block<N>;
60 let tail_ptr = data.as_ptr().add(blocks_len);
61 (
62 slice::from_raw_parts(blocks_ptr, nb),
63 slice::from_raw_parts(tail_ptr, tail_len),
64 )
65 }
66 }
67}
68