cbnf_rs/
lib.rs

1#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
2#![deny(clippy::unwrap_used, clippy::expect_used)]
3#![no_std]
4
5/// The header of a CBNF file.
6#[repr(C, packed)]
7pub struct CBNFHeader {
8    pub magic: [u8; 4],
9    pub version: u16,
10    pub flags: u16,
11    pub padding: u8,
12    pub arch: u8,
13    pub activation: u8,
14    pub hidden_size: u16,
15    pub input_buckets: u8,
16    pub output_buckets: u8,
17    pub name_len: u8,
18    pub name: [u8; 48],
19}
20
21const _ASSERT_SIZE: () = assert!(core::mem::size_of::<CBNFHeader>() == 64);
22
23impl CBNFHeader {
24    /// Parse a CBNF header from a byte slice.
25    /// Returns `None` if the data is too short or the magic number is incorrect.
26    #[must_use]
27    pub fn parse(data: &[u8]) -> Option<&Self> {
28        if data.len() < core::mem::size_of::<Self>() {
29            return None;
30        }
31
32        if &data[0..4] != b"CBNF" {
33            return None;
34        }
35
36        // SAFETY: We just checked that the data is at least as long as the header,
37        // and the header is packed, so there are no padding or alignment issues.
38        let header = unsafe { &*data.as_ptr().cast::<Self>() };
39
40        Some(header)
41    }
42
43    /// Get the name of the network as a UTF-8 string.
44    /// Truncates the name if the length field indicates a name longer than the
45    /// 48 bytes available in the header.
46    ///
47    /// # Errors
48    ///
49    /// Returns an error if the name is not valid UTF-8.
50    pub fn name(&self) -> Result<&str, core::str::Utf8Error> {
51        let rhs = core::cmp::min(self.name_len as usize, self.name.len());
52        core::str::from_utf8(&self.name[0..rhs])
53    }
54
55    /// Get the header as a byte slice.
56    #[must_use]
57    pub const fn as_bytes(&self) -> &[u8] {
58        const LEN: usize = core::mem::size_of::<CBNFHeader>();
59        let data = (self as *const Self).cast::<u8>();
60        // SAFETY: The header is packed, so there are no padding or alignment issues.
61        unsafe { core::slice::from_raw_parts(data, LEN) }
62    }
63}