yglnk-core 0.0.2

basic on-disk structured data helpers
Documentation
#![no_std]
#![forbid(unsafe_code)]

#[cfg(feature = "alloc")]
extern crate alloc;

pub use int_enum::{IntEnum, IntEnumError};

pub mod hash_table;
pub mod hilbert;
pub mod linear_table;

pub const MAGIC: [u8; 4] = [b'Y', b'g', b'L', b'n'];

#[derive(Clone, Copy, Debug, IntEnum)]
#[repr(u32)]
#[rustfmt::skip]
pub enum FileType {
    None        = 0x0000_0000,
    Text        = 0x0000_0001,
}

#[derive(Clone, Copy, Debug)]
pub struct FileHeader {
    pub magic: [u8; 4],
    pub generator: u32,
    pub typ: u32,
    pub version: u32,
}

impl FileHeader {
    pub fn decode(data: [u8; 16]) -> Self {
        Self {
            magic: data[0..4].try_into().unwrap(),
            generator: u32::from_be_bytes(data[4..8].try_into().unwrap()),
            typ: u32::from_be_bytes(data[8..12].try_into().unwrap()),
            version: u32::from_be_bytes(data[12..16].try_into().unwrap()),
        }
    }

    pub fn encode(&self) -> [u8; 16] {
        let mut data = [0u8; 16];
        data[0..4].copy_from_slice(&self.magic);
        data[4..8].copy_from_slice(&u32::to_be_bytes(self.generator));
        data[8..12].copy_from_slice(&u32::to_be_bytes(self.typ));
        data[12..16].copy_from_slice(&u32::to_be_bytes(self.version));
        data
    }
}

#[derive(Clone, Copy, Debug, IntEnum)]
#[repr(u32)]
#[rustfmt::skip]
pub enum Type {
    PlainText   = 0x0000_0000,
    NestedText  = 0x0000_0001,

    StringTable = 0x0000_0010,
    LinearPlain = 0x0000_0012,

    HashPlain   = 0x0000_0020,
    HashLink    = 0x0000_0021,

    X2dhcPlain  = 0x0000_0030,
    X2dhcLink   = 0x0000_0031,
}

#[derive(Clone, Copy, Debug, IntEnum)]
#[repr(u16)]
#[rustfmt::skip]
pub enum Ntt01 {
    Div         = 0x0000,
    Group       = 0x0001,
    Header      = 0x0002,
    Quote       = 0x0003,
    Code        = 0x0004,
}

pub fn trunc_key_at0(key: &[u8]) -> &[u8] {
    memchr::memchr(0, key)
        .map(|key_end| &key[..key_end])
        .unwrap_or(key)
}

#[inline]
pub fn decode_location(location: u32) -> Option<usize> {
    usize::try_from(location).ok()?.checked_mul(16)
}

/// A reference to a string table, including its data and location
#[derive(Clone, Copy)]
pub struct StrtabDescriptorRef<'a> {
    pub data: &'a [u8],

    /// as usual for yglnk, the location is specified in 16-byte units
    pub location: u32,
}

impl core::ops::Index<u32> for StrtabDescriptorRef<'_> {
    type Output = [u8];

    fn index(&self, index: u32) -> &[u8] {
        trunc_key_at0(&self.data[index.try_into().unwrap()..])
    }
}