1#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
2#![deny(clippy::unwrap_used, clippy::expect_used)]
3#![no_std]
4
5#[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 #[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 let header = unsafe { &*data.as_ptr().cast::<Self>() };
39
40 Some(header)
41 }
42
43 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 #[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 unsafe { core::slice::from_raw_parts(data, LEN) }
62 }
63}