use std::convert::TryFrom;
use crate::error::UnexpectedCode;
use lurk_ipld_core::ipld::Ipld;
#[repr(transparent)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Major(u8);
pub const FALSE: Major = Major::new(MajorKind::Other, 20);
pub const TRUE: Major = Major::new(MajorKind::Other, 21);
pub const NULL: Major = Major::new(MajorKind::Other, 22);
pub const F16: Major = Major::new(MajorKind::Other, 25);
pub const F32: Major = Major::new(MajorKind::Other, 26);
pub const F64: Major = Major::new(MajorKind::Other, 27);
impl Major {
const fn new(kind: MajorKind, info: u8) -> Self {
Major(((kind as u8) << 5) | info)
}
#[inline(always)]
pub const fn kind(self) -> MajorKind {
unsafe { std::mem::transmute(self.0 >> 5) }
}
#[inline(always)]
pub const fn info(self) -> u8 {
self.0 & 0x1f
}
#[inline(always)]
#[allow(clippy::len_without_is_empty)]
pub const fn len(self) -> u8 {
match self.info() {
info @ 24..=27 => 1 << (info - 24),
_ => 0,
}
}
}
impl From<Major> for u8 {
fn from(m: Major) -> u8 {
m.0
}
}
impl TryFrom<u8> for Major {
type Error = UnexpectedCode;
fn try_from(value: u8) -> Result<Self, Self::Error> {
if value & 28 == 28 {
return Err(UnexpectedCode::new::<Ipld>(value));
} else if (value >> 5) == MajorKind::Other as u8 {
match value & 0x1f {
20 | 21 | 22 => (),
25 | 26 | 27 => (),
_ => {
return Err(UnexpectedCode::new::<Ipld>(value));
}
}
}
Ok(Major(value))
}
}
#[repr(u8)]
#[derive(Clone, Copy, Eq, PartialEq)]
#[allow(dead_code)]
pub enum MajorKind {
UnsignedInt = 0,
NegativeInt = 1,
ByteString = 2,
TextString = 3,
Array = 4,
Map = 5,
Tag = 6,
Other = 7,
}