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