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
//! Various utility functions to be used in conjunction with ipv8

use std::error::Error;

create_error!(ConversionError, "Converting to a fixed size array failed.");

/// Helper function types which have the [FromBytes](zerocopy::FromBytes) trait to be converted to some fixed size variant.
/// Doesn't copy.
pub fn as_fixed_size<T>(data: &[u8]) -> Result<&T, Box<dyn Error>>
where
    T: zerocopy::FromBytes,
{
    Ok(
        (zerocopy::LayoutVerified::<_, T>::new(data).ok_or_else(|| Box::new(ConversionError))?)
            .into_ref(),
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_as_fixed_size_valid() {
        let data = &[0u8, 1u8, 2u8];
        let fixed: [u8; 3] = *as_fixed_size(data).unwrap();
        assert_eq!(fixed, [0u8, 1u8, 2u8]);
    }

    #[test]
    fn test_as_fixed_size_invalid_too_large() {
        let data = &[0u8, 1u8, 2u8];
        let fixed: Result<&[u8; 4], Box<dyn Error>> = as_fixed_size(data);

        match fixed {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        };
    }

    #[test]
    fn test_as_fixed_size_invalid_too_small() {
        let data = &[0u8, 1u8, 2u8];
        let fixed: Result<&[u8; 2], Box<dyn Error>> = as_fixed_size(data);

        match fixed {
            Ok(_) => assert!(false),
            Err(_) => assert!(true),
        };
    }

}