litl_val/
conversions.rs

1use std::ptr::NonNull;
2
3use nanval::cell::{
4    from_tag_and_data, from_tag_and_pointer, unwrap_cell, unwrap_cell_rawptr, unwrap_tag, CellTag,
5};
6use ordered_float::NotNan;
7
8use crate::ValRef;
9
10use super::{
11    key::{Key, ValKeyError},
12    key_e::KeyE,
13    map::Map,
14    map_ref::MapRef,
15    slim_boxed_slice::{slim_box_parts_for_slice, SlimBoxedSlice, SlimBoxedString},
16    tiny_string::TinyString,
17    val::Val,
18    val_e::ValE,
19};
20
21impl From<ValE> for Val {
22    #[inline]
23    fn from(val_e: ValE) -> Self {
24        match val_e {
25            ValE::Null => Self(f64::from_bits(from_tag_and_data(CellTag::Tag1, 2).unwrap())),
26            ValE::Bool(b) => Self(f64::from_bits(
27                from_tag_and_data(CellTag::Tag1, if b { 1 } else { 0 }).unwrap(),
28            )),
29            ValE::Number(num) => Self(num.into_inner()),
30            ValE::ShortString(s) => {
31                let bytes6 = s.to_bytes();
32                let bytes8: [u8; 8] = [
33                    bytes6[0], bytes6[1], bytes6[2], bytes6[3], bytes6[4], bytes6[5], 0, 0,
34                ];
35                Self(f64::from_bits(
36                    from_tag_and_data(CellTag::Tag2, u64::from_ne_bytes(bytes8)).unwrap(),
37                ))
38            }
39            ValE::LongString(slim_box) => Self(f64::from_bits(
40                from_tag_and_pointer(CellTag::Tag3, slim_box.into_raw() as *mut ()).unwrap(),
41            )),
42            ValE::Array(slim_box) => Self(f64::from_bits(
43                from_tag_and_pointer(CellTag::Tag4, slim_box.into_raw() as *mut ()).unwrap(),
44            )),
45            ValE::Object(map) => Self(f64::from_bits(
46                from_tag_and_pointer(CellTag::Tag5, map.into_raw() as *mut ()).unwrap(),
47            )),
48        }
49    }
50}
51
52impl From<Val> for ValE {
53    fn from(val: Val) -> Self {
54        match unwrap_tag(val.0) {
55            Some(CellTag::Tag1) => match unwrap_cell(val.0).unwrap() {
56                0 => ValE::Bool(false),
57                1 => ValE::Bool(true),
58                2 => ValE::Null,
59                _ => unreachable!("Invalid symbol value"),
60            },
61            Some(CellTag::Tag2) => {
62                let bytes8 = unwrap_cell(val.0).unwrap().to_ne_bytes();
63                let bytes6 = [
64                    bytes8[0], bytes8[1], bytes8[2], bytes8[3], bytes8[4], bytes8[5],
65                ];
66                ValE::ShortString(unsafe { TinyString::from_bytes_unchecked(bytes6) })
67            }
68            Some(CellTag::Tag3) => {
69                let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
70                ValE::LongString(unsafe { SlimBoxedString::from_raw(ptr) })
71            }
72            Some(CellTag::Tag4) => {
73                let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
74                ValE::Array(unsafe { SlimBoxedSlice::from_raw(ptr) })
75            }
76            Some(CellTag::Tag5) => {
77                let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
78                ValE::Object(unsafe { Map::from_raw(ptr) })
79            }
80            Some(_) => unreachable!("Invalid tag"),
81            None => ValE::Number(NotNan::new(val.0).unwrap()),
82        }
83    }
84}
85
86impl ValE {
87    pub fn as_ref(&self) -> ValRef {
88        match &self {
89            ValE::Null => ValRef::Null,
90            ValE::Bool(b) => ValRef::Bool(*b),
91            ValE::Number(n) => ValRef::Number(*n),
92            ValE::ShortString(s) => ValRef::String(s.as_ref()),
93            ValE::LongString(s) => ValRef::String(s.as_ref()),
94            ValE::Array(a) => ValRef::Array(a.as_ref()),
95            ValE::Object(o) => ValRef::Object(o.as_ref()),
96        }
97    }
98}
99
100impl Val {
101    #[inline]
102    pub fn direct_ref(&self) -> ValRef {
103        match unwrap_tag(self.0) {
104            Some(CellTag::Tag1) => match unwrap_cell(self.0).unwrap() {
105                0 => ValRef::Bool(false),
106                1 => ValRef::Bool(true),
107                2 => ValRef::Null,
108                _ => unreachable!("Invalid symbol value"),
109            },
110            Some(CellTag::Tag2) => unsafe {
111                let slice = (&*(&self.0 as *const f64 as *const [u8; 8])).get_unchecked(0..6);
112                let len = slice.iter().position(|&b| b == 0).unwrap_or(6);
113                ValRef::String(std::str::from_utf8_unchecked(&slice[0..len]))
114            },
115            Some(CellTag::Tag3) => {
116                let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
117                unsafe {
118                    let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
119                    ValRef::String(std::str::from_utf8_unchecked(std::slice::from_raw_parts(
120                        data, len,
121                    )))
122                }
123            }
124            Some(CellTag::Tag4) => {
125                let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
126                unsafe {
127                    let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
128                    ValRef::Array(std::slice::from_raw_parts(data, len))
129                }
130            }
131            Some(CellTag::Tag5) => {
132                let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
133                unsafe {
134                    let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
135                    ValRef::Object(MapRef(std::slice::from_raw_parts(data, len)))
136                }
137            }
138            Some(_) => unreachable!("Invalid tag"),
139            None => ValRef::Number(NotNan::new(self.0).unwrap()),
140        }
141    }
142}
143
144impl TryFrom<ValE> for KeyE {
145    type Error = ValKeyError;
146
147    #[inline]
148    fn try_from(value: ValE) -> Result<Self, Self::Error> {
149        match value {
150            ValE::Number(n) => Ok(ValE::string(n.to_string()).try_into().unwrap()),
151            ValE::ShortString(s) => Ok(KeyE::ShortString(s)),
152            ValE::LongString(s) => Ok(KeyE::LongString(s)),
153            _ => Err(ValKeyError::InvalidKey),
154        }
155    }
156}
157
158impl TryFrom<Val> for Key {
159    type Error = ValKeyError;
160
161    #[inline]
162    fn try_from(value: Val) -> Result<Self, Self::Error> {
163        let key: KeyE = Into::<ValE>::into(value).try_into()?;
164        Ok(key.into())
165    }
166}
167
168impl From<KeyE> for ValE {
169    #[inline]
170    fn from(key: KeyE) -> Self {
171        match key {
172            KeyE::ShortString(s) => ValE::ShortString(s),
173            KeyE::LongString(s) => ValE::LongString(s),
174        }
175    }
176}
177
178impl From<Key> for Val {
179    #[inline]
180    fn from(key: Key) -> Self {
181        key.0
182    }
183}
184
185impl From<Key> for KeyE {
186    #[inline]
187    fn from(key: Key) -> Self {
188        let c_value_e: ValE = key.0.into();
189        c_value_e.try_into().unwrap()
190    }
191}
192
193impl From<KeyE> for Key {
194    #[inline]
195    fn from(key: KeyE) -> Self {
196        let c_value_e: ValE = key.into();
197        Key(c_value_e.into())
198    }
199}