1#[repr(u8)]
6#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7pub enum Kind {
8 U8,
9 I32,
10 U32,
11 I64,
12 U64,
13 F32,
14 F64,
15}
16
17impl Kind {
18 pub const fn size(self) -> usize {
20 match self {
21 Kind::U8 => 1,
22 Kind::I32 | Kind::U32 | Kind::F32 => 4,
23 Kind::I64 | Kind::U64 | Kind::F64 => 8,
24 }
25 }
26
27 pub const fn code(self) -> u8 {
29 self as u8
30 }
31
32 pub const fn from_code(code: u8) -> Option<Kind> {
33 Some(match code {
34 0 => Kind::U8,
35 1 => Kind::I32,
36 2 => Kind::U32,
37 3 => Kind::I64,
38 4 => Kind::U64,
39 5 => Kind::F32,
40 6 => Kind::F64,
41 _ => return None,
42 })
43 }
44}
45
46pub trait Cell: Copy + Default + 'static {
48 const KIND: Kind;
49 const COUNT: u32;
50 const WIDTH: usize = Self::KIND.size() * Self::COUNT as usize;
52 fn put(&self, out: &mut [u8]);
54 fn take(bytes: &[u8]) -> Self;
56}
57
58macro_rules! numbers {
59 ($($t:ty => $kind:ident),* $(,)?) => {$(
60 impl Cell for $t {
61 const KIND: Kind = Kind::$kind;
62 const COUNT: u32 = 1;
63 #[inline]
64 fn put(&self, out: &mut [u8]) {
65 out[..Self::WIDTH].copy_from_slice(&self.to_le_bytes());
66 }
67 #[inline]
68 fn take(bytes: &[u8]) -> Self {
69 let mut b = [0u8; std::mem::size_of::<$t>()];
70 b.copy_from_slice(&bytes[..Self::WIDTH]);
71 <$t>::from_le_bytes(b)
72 }
73 }
74 )*};
75}
76
77numbers!(u8 => U8, i32 => I32, u32 => U32, i64 => I64, u64 => U64, f32 => F32, f64 => F64);
78
79impl Cell for bool {
80 const KIND: Kind = Kind::U8;
81 const COUNT: u32 = 1;
82 #[inline]
83 fn put(&self, out: &mut [u8]) {
84 out[0] = u8::from(*self);
85 }
86 #[inline]
87 fn take(bytes: &[u8]) -> Self {
88 bytes[0] != 0
89 }
90}
91
92impl<T: Cell, const N: usize> Cell for [T; N]
93where
94 [T; N]: Default,
95{
96 const KIND: Kind = T::KIND;
97 const COUNT: u32 = T::COUNT * N as u32;
98 #[inline]
99 fn put(&self, out: &mut [u8]) {
100 let out = &mut out[..Self::WIDTH];
101 for (i, v) in self.iter().enumerate() {
102 v.put(&mut out[i * T::WIDTH..]);
103 }
104 }
105 #[inline]
106 fn take(bytes: &[u8]) -> Self {
107 let bytes = &bytes[..Self::WIDTH];
108 std::array::from_fn(|i| T::take(&bytes[i * T::WIDTH..]))
109 }
110}
111
112pub const NO_ATOM: u32 = u32::MAX;
114
115impl Cell for Option<yog_data::Atom> {
118 const KIND: Kind = Kind::U32;
119 const COUNT: u32 = 1;
120
121 #[inline]
122 fn put(&self, out: &mut [u8]) {
123 self.map_or(NO_ATOM, yog_data::Atom::number).put(out);
124 }
125
126 #[inline]
127 fn take(bytes: &[u8]) -> Self {
128 match u32::take(bytes) {
129 NO_ATOM => None,
130 n => yog_data::Atom::from_number(n),
131 }
132 }
133}