serde-beve 1.0.0

A BEVE data format for Serde
Documentation
use crate::Value;

pub const NULL: u8 = 0;
pub const FALSE: u8 = 0b00001000;
pub const TRUE: u8 = 0b00011000;

pub const BF16: u8 = 0b00000001;
pub const F16: u8 = 0b000100001;
pub const F32: u8 = 0b01000001;
pub const F64: u8 = 0b01100001;
pub const F128: u8 = 0b10000001;

pub const I8: u8 = 0b00001001;
pub const I16: u8 = 0b00101001;
pub const I32: u8 = 0b01001001;
pub const I64: u8 = 0b01101001;
pub const I128: u8 = 0b10001001;

pub const U8: u8 = 0b00010001;
pub const U16: u8 = 0b00110001;
pub const U32: u8 = 0b01010001;
pub const U64: u8 = 0b01110001;
pub const U128: u8 = 0b10010001;

pub const STRING: u8 = 0b00000010;

pub const STRING_OBJECT: u8 = 0b00000011;

pub const I8_OBJECT: u8 = 0b00001011;
pub const I16_OBJECT: u8 = 0b00101011;
pub const I32_OBJECT: u8 = 0b01001011;
pub const I64_OBJECT: u8 = 0b01101011;
pub const I128_OBJECT: u8 = 0b10001011;

pub const U8_OBJECT: u8 = 0b00010011;
pub const U16_OBJECT: u8 = 0b00110011;
pub const U32_OBJECT: u8 = 0b01010011;
pub const U64_OBJECT: u8 = 0b01110011;
pub const U128_OBJECT: u8 = 0b10010011;

pub const BF16_ARRAY: u8 = 0b00000100;
pub const F16_ARRAY: u8 = 0b00100100;
pub const F32_ARRAY: u8 = 0b01000100;
pub const F64_ARRAY: u8 = 0b01100100;
pub const F128_ARRAY: u8 = 0b10000100;

pub const I8_ARRAY: u8 = 0b00001100;
pub const I16_ARRAY: u8 = 0b00101100;
pub const I32_ARRAY: u8 = 0b01001100;
pub const I64_ARRAY: u8 = 0b01101100;
pub const I128_ARRAY: u8 = 0b10001100;

pub const U8_ARRAY: u8 = 0b00010100;
pub const U16_ARRAY: u8 = 0b00110100;
pub const U32_ARRAY: u8 = 0b01010100;
pub const U64_ARRAY: u8 = 0b01110100;
pub const U128_ARRAY: u8 = 0b10010100;

pub const BOOL_ARRAY: u8 = 0b00011100;
pub const STRING_ARRAY: u8 = 0b00111100;
pub const GENERIC_ARRAY: u8 = 0b00000101;

pub const DELIMITER: u8 = 0b00000110;
pub const TAG: u8 = 0b00001110;
pub const MATRIX: u8 = 0b00010110;
pub const COMPLEX: u8 = 0b00011110;

pub const RESERVED: u8 = 0b00000111;

pub const fn header_name(header: u8) -> &'static str {
    match header {
        NULL => "null",
        FALSE | TRUE => "boolean",

        BF16 => "brain float",
        F16 => "16-bit float",
        F32 => "32-bit float",
        F64 => "64-bit float",
        F128 => "128-bit float",

        I8 => "8-bit integer",
        I16 => "16-bit integer",
        I32 => "32-bit integer",
        I64 => "64-bit integer",
        I128 => "128-bit integer",

        U8 => "8-bit unsigned integer",
        U16 => "16-bit unsigned integer",
        U32 => "32-bit unsigned integer",
        U64 => "64-bit unsigned integer",
        U128 => "128-bit unsigned integer",

        STRING => "string",

        STRING_OBJECT => "string-keyed object",

        I8_OBJECT => "8-bit integer-keyed object",
        I16_OBJECT => "16-bit integer-keyed object",
        I32_OBJECT => "32-bit integer-keyed object",
        I64_OBJECT => "64-bit integer-keyed object",
        I128_OBJECT => "128-bit integer-keyed object",

        U8_OBJECT => "unsigned 8-bit integer-keyed object",
        U16_OBJECT => "unsigned 16-bit integer-keyed object",
        U32_OBJECT => "unsigned 32-bit integer-keyed object",
        U64_OBJECT => "unsigned 64-bit integer-keyed object",
        U128_OBJECT => "unsigned 128-bit integer-keyed object",

        BF16_ARRAY => "array of brain floats",
        F16_ARRAY => "array of 16-bit floats",
        F32_ARRAY => "array of 32-bit floats",
        F64_ARRAY => "array of 64-bit floats",
        F128_ARRAY => "array of 128-bit floats",

        I8_ARRAY => "array of 8-bit integers",
        I16_ARRAY => "array of 16-bit integers",
        I32_ARRAY => "array of 32-bit integers",
        I64_ARRAY => "array of 64-bit integers",
        I128_ARRAY => "array of 128-bit integers",

        U8_ARRAY => "array of 8-bit unsigned integers",
        U16_ARRAY => "array of 16-bit unsigned integers",
        U32_ARRAY => "array of 32-bit unsigned integers",
        U64_ARRAY => "array of 64-bit unsigned integers",
        U128_ARRAY => "array of 128-bit unsigned integers",

        BOOL_ARRAY => "array of booleans",
        STRING_ARRAY => "array of strings",
        GENERIC_ARRAY => "generic array",

        DELIMITER => "data delimiter",
        TAG => "type tag",
        MATRIX => "matrix",
        COMPLEX => "complex number",

        RESERVED => "reserved",
        _ => "unknown type",
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArrayKind {
    Generic,
    String,
    Boolean,
    I8,
    I16,
    I32,
    I64,
    I128,
    U8,
    U16,
    U32,
    U64,
    U128,
    BF16,
    F16,
    F32,
    F64,
    F128,
    Complex,
}

impl From<&Value> for ArrayKind {
    fn from(value: &Value) -> Self {
        match value {
            Value::I8(..) => Self::I8,
            Value::I16(..) => Self::I16,
            Value::I32(..) => Self::I32,
            Value::I64(..) => Self::I64,
            Value::I128(..) => Self::I128,
            Value::U8(..) => Self::U8,
            Value::U16(..) => Self::U16,
            Value::U32(..) => Self::U32,
            Value::U64(..) => Self::U64,
            Value::U128(..) => Self::U128,
            #[cfg(feature = "half")]
            Value::BF16(..) => Self::BF16,
            #[cfg(not(feature = "half"))]
            Value::BF16 => Self::BF16,
            #[cfg(feature = "half")]
            Value::F16(..) => Self::F16,
            #[cfg(not(feature = "half"))]
            Value::F16 => Self::F16,
            Value::F32(..) => Self::F32,
            Value::F64(..) => Self::F64,
            Value::F128 => Self::F128,
            Value::Complex(..) => unreachable!(),
            Value::String(..) => Self::String,
            Value::True | Value::False => Self::Boolean,
            _ => Self::Generic,
        }
    }
}

impl ArrayKind {
    pub const fn header(self) -> u8 {
        match self {
            Self::Generic => GENERIC_ARRAY,
            Self::String => STRING_ARRAY,
            Self::Boolean => BOOL_ARRAY,
            Self::I8 => I8_ARRAY,
            Self::I16 => I16_ARRAY,
            Self::I32 => I32_ARRAY,
            Self::I64 => I64_ARRAY,
            Self::I128 => I128_ARRAY,
            Self::U8 => U8_ARRAY,
            Self::U16 => U16_ARRAY,
            Self::U32 => U32_ARRAY,
            Self::U64 => U64_ARRAY,
            Self::U128 => U128_ARRAY,
            Self::BF16 => BF16_ARRAY,
            Self::F16 => F16_ARRAY,
            Self::F32 => F32_ARRAY,
            Self::F64 => F64_ARRAY,
            Self::F128 => F128,
            Self::Complex => COMPLEX,
        }
    }
}

impl std::fmt::Display for ArrayKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Generic => write!(f, "{}", header_name(GENERIC_ARRAY)),
            Self::String => write!(f, "{}", header_name(STRING)),
            Self::Boolean => write!(f, "{}", header_name(TRUE)),
            Self::I8 => write!(f, "{}", header_name(I8)),
            Self::I16 => write!(f, "{}", header_name(I16)),
            Self::I32 => write!(f, "{}", header_name(I32)),
            Self::I64 => write!(f, "{}", header_name(I64)),
            Self::I128 => write!(f, "{}", header_name(I128)),
            Self::U8 => write!(f, "{}", header_name(U8)),
            Self::U16 => write!(f, "{}", header_name(U16)),
            Self::U32 => write!(f, "{}", header_name(U32)),
            Self::U64 => write!(f, "{}", header_name(U64)),
            Self::U128 => write!(f, "{}", header_name(U128)),
            Self::BF16 => write!(f, "{}", header_name(BF16)),
            Self::F16 => write!(f, "{}", header_name(F16)),
            Self::F32 => write!(f, "{}", header_name(F32)),
            Self::F64 => write!(f, "{}", header_name(F64)),
            Self::F128 => write!(f, "{}", header_name(F128)),
            Self::Complex => write!(f, "{}", header_name(COMPLEX)),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ObjectKind {
    U8,
    U16,
    U32,
    U64,
    U128,
    I8,
    I16,
    I32,
    I64,
    I128,
    String,
}

impl ObjectKind {
    pub const fn header(self) -> u8 {
        match self {
            Self::U8 => U8_OBJECT,
            Self::U16 => U16_OBJECT,
            Self::U32 => U32_OBJECT,
            Self::U64 => U64_OBJECT,
            Self::U128 => U128_OBJECT,
            Self::I8 => I8_OBJECT,
            Self::I16 => I16_OBJECT,
            Self::I32 => I32_OBJECT,
            Self::I64 => I64_OBJECT,
            Self::I128 => I128_OBJECT,
            Self::String => STRING_OBJECT,
        }
    }
}

impl std::fmt::Display for ObjectKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::U8 => write!(f, "{}", header_name(U8)),
            Self::U16 => write!(f, "{}", header_name(U16)),
            Self::U32 => write!(f, "{}", header_name(U32)),
            Self::U64 => write!(f, "{}", header_name(U64)),
            Self::U128 => write!(f, "{}", header_name(U128)),
            Self::I8 => write!(f, "{}", header_name(I8)),
            Self::I16 => write!(f, "{}", header_name(I16)),
            Self::I32 => write!(f, "{}", header_name(I32)),
            Self::I64 => write!(f, "{}", header_name(I64)),
            Self::I128 => write!(f, "{}", header_name(I128)),
            Self::String => write!(f, "{}", header_name(STRING)),
        }
    }
}

impl TryFrom<&Value> for ObjectKind {
    type Error = crate::Error;

    fn try_from(value: &Value) -> Result<Self, Self::Error> {
        Ok(match value {
            Value::I8(..) => Self::I8,
            Value::I16(..) => Self::I16,
            Value::I32(..) => Self::I32,
            Value::I64(..) => Self::I64,
            Value::I128(..) => Self::I128,
            Value::U8(..) => Self::U8,
            Value::U16(..) => Self::U16,
            Value::U32(..) => Self::U32,
            Value::U64(..) => Self::U64,
            Value::U128(..) => Self::U128,
            Value::String(..) => Self::String,
            _ => return Err(crate::Error::InvalidKey),
        })
    }
}

pub const NUM_TYPE_MASK: u8 = 0b11111000;

// Just the bits representing the size of the number
pub const I8_HEADER: u8 = I8 & NUM_TYPE_MASK;
pub const I16_HEADER: u8 = I16 & NUM_TYPE_MASK;
pub const I32_HEADER: u8 = I32 & NUM_TYPE_MASK;
pub const I64_HEADER: u8 = I64 & NUM_TYPE_MASK;
pub const I128_HEADER: u8 = I128 & NUM_TYPE_MASK;
pub const U8_HEADER: u8 = U8 & NUM_TYPE_MASK;
pub const U16_HEADER: u8 = U16 & NUM_TYPE_MASK;
pub const U32_HEADER: u8 = U32 & NUM_TYPE_MASK;
pub const U64_HEADER: u8 = U64 & NUM_TYPE_MASK;
pub const U128_HEADER: u8 = U128 & NUM_TYPE_MASK;
pub const F32_HEADER: u8 = F32 & NUM_TYPE_MASK;
pub const F64_HEADER: u8 = F64 & NUM_TYPE_MASK;