block_buffer/
sealed.rs

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 = data.len() / N::USIZE;
23        let blocks_len = nb * N::USIZE;
24        let tail_len = data.len() - blocks_len;
25        // SAFETY: we guarantee that created slices do not point
26        // outside of `data`
27        unsafe {
28            let blocks_ptr = data.as_ptr() as *const Block<N>;
29            let tail_ptr = data.as_ptr().add(blocks_len);
30            (
31                slice::from_raw_parts(blocks_ptr, nb),
32                slice::from_raw_parts(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}