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}