fuel_types/
bytes.rs

1use crate::Word;
2
3/// Size of a word, in bytes
4pub const WORD_SIZE: usize = core::mem::size_of::<Word>();
5
6/// Return the word-padded length of the buffer.
7/// Returns None if the length is too large to be represented as usize.
8pub const fn padded_len(bytes: &[u8]) -> Option<usize> {
9    padded_len_usize(bytes.len())
10}
11
12/// Return the word-padded length of an arbitrary length.
13/// Returns None if the length is too large to be represented as usize.
14#[allow(clippy::arithmetic_side_effects)] // Safety: (a % b) < b
15pub const fn padded_len_usize(len: usize) -> Option<usize> {
16    let modulo = len % WORD_SIZE;
17    if modulo == 0 {
18        Some(len)
19    } else {
20        let padding = WORD_SIZE - modulo;
21        len.checked_add(padding)
22    }
23}
24
25/// Return the word-padded length of an arbitrary length.
26/// Returns None if the length is too large to be represented as `Word`.
27#[allow(clippy::arithmetic_side_effects)] // Safety: (a % b) < b
28pub const fn padded_len_word(len: Word) -> Option<Word> {
29    let modulo = len % WORD_SIZE as Word;
30    if modulo == 0 {
31        Some(len)
32    } else {
33        let padding = WORD_SIZE as Word - modulo;
34        len.checked_add(padding)
35    }
36}
37
38#[cfg(feature = "unsafe")]
39#[allow(unsafe_code)]
40/// Add a conversion from arbitrary slices into arrays
41///
42/// # Safety
43///
44/// This function will not panic if the length of the slice is smaller than `N`. Instead,
45/// it will cause undefined behavior and read random disowned bytes.
46pub unsafe fn from_slice_unchecked<const N: usize>(buf: &[u8]) -> [u8; N] {
47    unsafe {
48        let ptr = buf.as_ptr() as *const [u8; N];
49
50        // Static assertions are not applicable to runtime length check (e.g. slices).
51        // This is safe if the size of `bytes` is consistent to `N`
52        *ptr
53    }
54}
55
56#[test]
57#[allow(clippy::erasing_op)]
58#[allow(clippy::identity_op)]
59fn padded_len_returns_multiple_of_word_len() {
60    assert_eq!(Some(WORD_SIZE * 0), padded_len(&[]));
61    assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0]));
62    assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0; WORD_SIZE]));
63    assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE + 1]));
64    assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE * 2]));
65}
66
67#[test]
68fn padded_len_usize_returns_multiple_of_word_len() {
69    assert_eq!(padded_len_usize(0), Some(0));
70    assert_eq!(padded_len_usize(1), Some(8));
71    assert_eq!(padded_len_usize(2), Some(8));
72    assert_eq!(padded_len_usize(7), Some(8));
73    assert_eq!(padded_len_usize(8), Some(8));
74    assert_eq!(padded_len_usize(9), Some(16));
75}
76
77#[test]
78fn padded_len_usize_handles_overflow() {
79    for i in 0..7 {
80        assert_eq!(padded_len_usize(usize::MAX - i), None);
81    }
82    assert_eq!(padded_len_usize(usize::MAX - 7), Some(usize::MAX - 7));
83}