use value_trait::{base::TypedValue as _, StaticNode, TryTypeError, ValueType};
pub(super) mod array;
mod cmp;
pub(super) mod object;
mod trait_impls;
#[derive(Debug)]
pub struct Tape<'input>(pub Vec<Node<'input>>);
pub use array::Array;
pub use object::Object;
impl<'input> Tape<'input> {
#[must_use]
pub fn as_value(&self) -> Value<'_, 'input> {
Value(&self.0)
}
#[must_use]
pub fn null() -> Self {
Self(vec![Node::Static(StaticNode::Null)])
}
#[must_use]
pub fn reset<'new>(mut self) -> Tape<'new> {
self.0.clear();
unsafe { std::mem::transmute(self) }
}
#[cfg(feature = "serde")]
pub fn deserialize<T>(self) -> crate::Result<T>
where
T: serde::Deserialize<'input>,
{
use crate::Deserializer;
let mut deserializer = Deserializer {
tape: self.0,
idx: 0,
};
T::deserialize(&mut deserializer)
}
}
#[derive(Clone, Copy, Debug)]
#[repr(transparent)]
pub struct Value<'tape, 'input>(pub(super) &'tape [Node<'input>])
where
'input: 'tape;
impl Value<'static, 'static> {
const NULL_TAPE: [Node<'static>; 1] = [Node::Static(StaticNode::Null)];
pub const NULL: Value<'static, 'static> = Value(&Self::NULL_TAPE);
#[must_use]
pub const fn null() -> Self {
Self::NULL
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Node<'input> {
String(&'input str),
Object {
len: usize,
count: usize,
},
Array {
len: usize,
count: usize,
},
Static(StaticNode),
}
impl<'input> Node<'input> {
fn as_str(&self) -> Option<&'input str> {
if let Node::String(s) = self {
Some(*s)
} else {
None
}
}
#[must_use]
pub fn value_type(&self) -> ValueType {
match self {
Node::String(_) => ValueType::String,
Node::Object { .. } => ValueType::Object,
Node::Array { .. } => ValueType::Array,
Node::Static(v) => v.value_type(),
}
}
fn array_count(&self) -> Result<usize, TryTypeError> {
if let Node::Array { count, .. } = self {
Ok(*count)
} else {
Err(TryTypeError {
expected: ValueType::Array,
got: self.value_type(),
})
}
}
fn object_count(&self) -> Result<usize, TryTypeError> {
if let Node::Object { count, .. } = self {
Ok(*count)
} else {
Err(TryTypeError {
expected: ValueType::Object,
got: self.value_type(),
})
}
}
fn object_len(&self) -> Result<usize, TryTypeError> {
if let Node::Object { len, .. } = self {
Ok(*len)
} else {
Err(TryTypeError {
expected: ValueType::Object,
got: self.value_type(),
})
}
}
fn count(&self) -> usize {
match self {
Node::Object { count, .. } | Node::Array { count, .. } => *count + 1,
_ => 1,
}
}
}
#[cfg(test)]
mod test {
#![allow(clippy::cognitive_complexity)]
use super::StaticNode as Value;
use super::*;
use crate::prelude::*;
#[test]
#[should_panic = "Not supported"]
#[allow(unused_variables, clippy::no_effect)]
fn object_index() {
let v = StaticNode::Null;
v["test"];
}
#[test]
#[should_panic = "Not supported"]
fn mut_object_index() {
let mut v = StaticNode::Null;
v["test"] = ();
}
#[test]
#[should_panic = "Not supported"]
#[allow(unused_variables, clippy::no_effect)]
fn array_index() {
let v = StaticNode::Null;
v[0];
}
#[test]
#[should_panic = "Not supported"]
fn mut_array_index() {
let mut v = StaticNode::Null;
v[0] = ();
}
#[test]
fn conversion_str() {
let v = StaticNode::Null;
assert!(!v.is_str());
}
#[cfg(feature = "128bit")]
#[test]
fn conversions_i128() {
let v = Value::from(i128::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(i128::MIN);
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_i64() {
let v = Value::from(i64::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(i64::MIN);
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_i32() {
let v = Value::from(i32::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(i32::MIN);
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_i16() {
let v = Value::from(i16::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(i16::MIN);
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_i8() {
let v = Value::from(i8::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(i8::MIN);
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(v.is_i16());
assert!(!v.is_u16());
assert!(v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_usize() {
let v = Value::from(usize::MIN as u64);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_usize());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[cfg(feature = "128bit")]
#[test]
fn conversions_u128() {
let v = Value::from(u128::MIN);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_u64() {
let v = Value::from(u64::MIN);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_u32() {
let v = Value::from(u32::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(!v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_u16() {
let v = Value::from(u16::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_u8() {
let v = Value::from(u8::MAX);
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(v.is_u8());
assert!(!v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_f64() {
let v = Value::from(f64::MAX);
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(f64::MIN);
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(v.is_f64());
assert!(!v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(());
assert!(!v.is_f64_castable());
}
#[test]
fn conversions_f32() {
let v = Value::from(f32::MAX);
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(v.is_f64());
assert!(v.is_f32());
assert!(v.is_f64_castable());
let v = Value::from(f32::MIN);
assert!(!v.is_i64());
assert!(!v.is_u64());
assert!(v.is_f64());
assert!(v.is_f32());
assert!(v.is_f64_castable());
}
#[test]
fn conversions_bool() {
let v = Value::from(true);
assert!(v.is_bool());
assert_eq!(v.value_type(), ValueType::Bool);
let v = Value::from(());
assert!(!v.is_bool());
}
#[test]
fn conversions_float() {
let v = Value::from(42.0);
assert!(v.is_f64());
assert_eq!(v.value_type(), ValueType::F64);
let v = Value::from(());
assert!(!v.is_f64());
}
#[test]
fn conversions_int() {
let v = Value::from(-42);
assert!(v.is_i64());
assert_eq!(v.value_type(), ValueType::I64);
#[cfg(feature = "128bit")]
{
let v = Value::from(-42_i128);
assert!(v.is_i64());
assert!(v.is_i128());
assert_eq!(v.value_type(), ValueType::I128);
}
let v = Value::from(());
assert!(!v.is_i64());
assert!(!v.is_i128());
}
#[test]
fn conversions_uint() {
let v = Value::from(42_u64);
assert!(v.is_u64());
assert_eq!(v.value_type(), ValueType::U64);
#[cfg(feature = "128bit")]
{
let v = Value::from(42_u128);
assert!(v.is_u64());
assert!(v.is_u128());
assert_eq!(v.value_type(), ValueType::U128);
}
let v = Value::from(());
assert!(!v.is_u64());
assert!(!v.is_u128());
}
#[test]
fn conversions_null() {
let v = Value::from(());
assert!(v.is_null());
assert_eq!(v.value_type(), ValueType::Null);
let v = Value::from(1);
assert!(!v.is_null());
}
#[test]
fn default() {
assert_eq!(Value::default(), Value::Null);
}
#[test]
fn mixed_int_cmp() {
assert_eq!(Value::from(1_u64), Value::from(1_i64));
assert_eq!(Value::from(1_i64), Value::from(1_u64));
}
#[test]
#[cfg(feature = "128bit")]
fn mixed_int_cmp_128() {
assert_eq!(Value::from(1_u64), Value::from(1_u128));
assert_eq!(Value::from(1_u64), Value::from(1_i128));
assert_eq!(Value::from(1_i64), Value::from(1_u128));
assert_eq!(Value::from(1_i64), Value::from(1_i128));
assert_eq!(Value::from(1_u128), Value::from(1_u128));
assert_eq!(Value::from(1_u128), Value::from(1_i128));
assert_eq!(Value::from(1_u128), Value::from(1_u64));
assert_eq!(Value::from(1_u128), Value::from(1_i64));
assert_eq!(Value::from(1_i128), Value::from(1_u128));
assert_eq!(Value::from(1_i128), Value::from(1_i128));
assert_eq!(Value::from(1_i128), Value::from(1_u64));
assert_eq!(Value::from(1_i128), Value::from(1_i64));
}
#[test]
fn test_union_cmp() {
let v: Value = ().into();
assert_eq!(v, ());
}
#[test]
#[allow(clippy::bool_assert_comparison)]
fn test_bool_cmp() {
let v: Value = true.into();
assert_eq!(v, true);
let v: Value = false.into();
assert_eq!(v, false);
}
}