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    let ptr = buf.as_ptr() as *const [u8; N];
48
49    // Static assertions are not applicable to runtime length check (e.g. slices).
50    // This is safe if the size of `bytes` is consistent to `N`
51    *ptr
52}
53
54#[test]
55#[allow(clippy::erasing_op)]
56#[allow(clippy::identity_op)]
57fn padded_len_returns_multiple_of_word_len() {
58    assert_eq!(Some(WORD_SIZE * 0), padded_len(&[]));
59    assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0]));
60    assert_eq!(Some(WORD_SIZE * 1), padded_len(&[0; WORD_SIZE]));
61    assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE + 1]));
62    assert_eq!(Some(WORD_SIZE * 2), padded_len(&[0; WORD_SIZE * 2]));
63}
64
65#[test]
66fn padded_len_usize_returns_multiple_of_word_len() {
67    assert_eq!(padded_len_usize(0), Some(0));
68    assert_eq!(padded_len_usize(1), Some(8));
69    assert_eq!(padded_len_usize(2), Some(8));
70    assert_eq!(padded_len_usize(7), Some(8));
71    assert_eq!(padded_len_usize(8), Some(8));
72    assert_eq!(padded_len_usize(9), Some(16));
73}
74
75#[test]
76fn padded_len_usize_handles_overflow() {
77    for i in 0..7 {
78        assert_eq!(padded_len_usize(usize::MAX - i), None);
79    }
80    assert_eq!(padded_len_usize(usize::MAX - 7), Some(usize::MAX - 7));
81}