1 | use super::{ArrayLength, Block}; |
2 | use core::slice; |
3 | |
4 | /// Sealed trait for buffer kinds. |
5 | pub 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 | |
14 | impl 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 | |
38 | impl 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 | |