use std::ptr::NonNull;
use nanval::cell::{
from_tag_and_data, from_tag_and_pointer, unwrap_cell, unwrap_cell_rawptr, unwrap_tag, CellTag,
};
use ordered_float::NotNan;
use crate::ValRef;
use super::{
key::{Key, ValKeyError},
key_e::KeyE,
map::Map,
map_ref::MapRef,
slim_boxed_slice::{slim_box_parts_for_slice, SlimBoxedSlice, SlimBoxedString},
tiny_string::TinyString,
val::Val,
val_e::ValE,
};
impl From<ValE> for Val {
#[inline]
fn from(val_e: ValE) -> Self {
match val_e {
ValE::Null => Self(f64::from_bits(from_tag_and_data(CellTag::Tag1, 2).unwrap())),
ValE::Bool(b) => Self(f64::from_bits(
from_tag_and_data(CellTag::Tag1, if b { 1 } else { 0 }).unwrap(),
)),
ValE::Number(num) => Self(num.into_inner()),
ValE::ShortString(s) => {
let bytes6 = s.to_bytes();
let bytes8: [u8; 8] = [
bytes6[0], bytes6[1], bytes6[2], bytes6[3], bytes6[4], bytes6[5], 0, 0,
];
Self(f64::from_bits(
from_tag_and_data(CellTag::Tag2, u64::from_ne_bytes(bytes8)).unwrap(),
))
}
ValE::LongString(slim_box) => Self(f64::from_bits(
from_tag_and_pointer(CellTag::Tag3, slim_box.into_raw() as *mut ()).unwrap(),
)),
ValE::Array(slim_box) => Self(f64::from_bits(
from_tag_and_pointer(CellTag::Tag4, slim_box.into_raw() as *mut ()).unwrap(),
)),
ValE::Object(map) => Self(f64::from_bits(
from_tag_and_pointer(CellTag::Tag5, map.into_raw() as *mut ()).unwrap(),
)),
}
}
}
impl From<Val> for ValE {
fn from(val: Val) -> Self {
match unwrap_tag(val.0) {
Some(CellTag::Tag1) => match unwrap_cell(val.0).unwrap() {
0 => ValE::Bool(false),
1 => ValE::Bool(true),
2 => ValE::Null,
_ => unreachable!("Invalid symbol value"),
},
Some(CellTag::Tag2) => {
let bytes8 = unwrap_cell(val.0).unwrap().to_ne_bytes();
let bytes6 = [
bytes8[0], bytes8[1], bytes8[2], bytes8[3], bytes8[4], bytes8[5],
];
ValE::ShortString(unsafe { TinyString::from_bytes_unchecked(bytes6) })
}
Some(CellTag::Tag3) => {
let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
ValE::LongString(unsafe { SlimBoxedString::from_raw(ptr) })
}
Some(CellTag::Tag4) => {
let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
ValE::Array(unsafe { SlimBoxedSlice::from_raw(ptr) })
}
Some(CellTag::Tag5) => {
let ptr = unwrap_cell_rawptr(val.0).unwrap() as *mut ();
ValE::Object(unsafe { Map::from_raw(ptr) })
}
Some(_) => unreachable!("Invalid tag"),
None => ValE::Number(NotNan::new(val.0).unwrap()),
}
}
}
impl ValE {
pub fn as_ref(&self) -> ValRef {
match &self {
ValE::Null => ValRef::Null,
ValE::Bool(b) => ValRef::Bool(*b),
ValE::Number(n) => ValRef::Number(*n),
ValE::ShortString(s) => ValRef::String(s.as_ref()),
ValE::LongString(s) => ValRef::String(s.as_ref()),
ValE::Array(a) => ValRef::Array(a.as_ref()),
ValE::Object(o) => ValRef::Object(o.as_ref()),
}
}
}
impl Val {
#[inline]
pub fn direct_ref(&self) -> ValRef {
match unwrap_tag(self.0) {
Some(CellTag::Tag1) => match unwrap_cell(self.0).unwrap() {
0 => ValRef::Bool(false),
1 => ValRef::Bool(true),
2 => ValRef::Null,
_ => unreachable!("Invalid symbol value"),
},
Some(CellTag::Tag2) => unsafe {
let slice = (&*(&self.0 as *const f64 as *const [u8; 8])).get_unchecked(0..6);
let len = slice.iter().position(|&b| b == 0).unwrap_or(6);
ValRef::String(std::str::from_utf8_unchecked(&slice[0..len]))
},
Some(CellTag::Tag3) => {
let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
unsafe {
let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
ValRef::String(std::str::from_utf8_unchecked(std::slice::from_raw_parts(
data, len,
)))
}
}
Some(CellTag::Tag4) => {
let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
unsafe {
let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
ValRef::Array(std::slice::from_raw_parts(data, len))
}
}
Some(CellTag::Tag5) => {
let ptr = unwrap_cell_rawptr(self.0).unwrap() as *mut ();
unsafe {
let (data, len) = slim_box_parts_for_slice(NonNull::new(ptr as *mut i32));
ValRef::Object(MapRef(std::slice::from_raw_parts(data, len)))
}
}
Some(_) => unreachable!("Invalid tag"),
None => ValRef::Number(NotNan::new(self.0).unwrap()),
}
}
}
impl TryFrom<ValE> for KeyE {
type Error = ValKeyError;
#[inline]
fn try_from(value: ValE) -> Result<Self, Self::Error> {
match value {
ValE::Number(n) => Ok(ValE::string(n.to_string()).try_into().unwrap()),
ValE::ShortString(s) => Ok(KeyE::ShortString(s)),
ValE::LongString(s) => Ok(KeyE::LongString(s)),
_ => Err(ValKeyError::InvalidKey),
}
}
}
impl TryFrom<Val> for Key {
type Error = ValKeyError;
#[inline]
fn try_from(value: Val) -> Result<Self, Self::Error> {
let key: KeyE = Into::<ValE>::into(value).try_into()?;
Ok(key.into())
}
}
impl From<KeyE> for ValE {
#[inline]
fn from(key: KeyE) -> Self {
match key {
KeyE::ShortString(s) => ValE::ShortString(s),
KeyE::LongString(s) => ValE::LongString(s),
}
}
}
impl From<Key> for Val {
#[inline]
fn from(key: Key) -> Self {
key.0
}
}
impl From<Key> for KeyE {
#[inline]
fn from(key: Key) -> Self {
let c_value_e: ValE = key.0.into();
c_value_e.try_into().unwrap()
}
}
impl From<KeyE> for Key {
#[inline]
fn from(key: KeyE) -> Self {
let c_value_e: ValE = key.into();
Key(c_value_e.into())
}
}