1use std::{
2 fmt::Debug,
3 hash::{Hash, Hasher},
4 ops::Index,
5};
6
7use deepsize::DeepSizeOf;
8use ordered_float::NotNan;
9
10use super::{key_e::KeyE, slim_boxed_slice::SlimBoxedSlice, val_ref::ValRef, Map, ValE};
11
12pub struct Val(pub(crate) f64);
13
14impl Val {
15 #[inline]
16 pub fn str(s: &str) -> Val {
17 ValE::str(s).into()
18 }
19
20 #[inline]
21 pub fn string(s: String) -> Val {
22 ValE::string(s).into()
23 }
24
25 #[inline]
26 pub fn number(n: f64) -> Val {
27 ValE::Number(NotNan::new(n).unwrap()).into()
28 }
29
30 #[inline]
31 pub fn bool(b: bool) -> Val {
32 ValE::Bool(b).into()
33 }
34
35 #[inline]
36 pub fn null() -> Val {
37 ValE::Null.into()
38 }
39
40 #[inline]
41 pub fn array<V: Into<Val>, I: IntoIterator<Item = V>>(items: I) -> Val {
42 ValE::Array(SlimBoxedSlice::from_vec(
43 items.into_iter().map(Into::into).collect::<Vec<_>>(),
44 ))
45 .into()
46 }
47
48 #[inline]
49 pub fn object<K: ToString, V: Into<Val>, I: IntoIterator<Item = (K, V)>>(items: I) -> Val {
50 ValE::Object(Map::new(
51 items
52 .into_iter()
53 .map(|(k, v)| (KeyE::string(k.to_string()).into(), v.into()))
54 .collect::<Vec<_>>(),
55 ))
56 .into()
57 }
58
59 #[inline]
60 pub fn as_str(&self) -> Option<&str> {
61 self.direct_ref().as_str()
62 }
63
64 #[inline]
65 pub fn is_null(&self) -> bool {
66 matches!(self.direct_ref(), ValRef::Null)
67 }
68
69 #[inline]
70 pub fn get<S: AsRef<str>>(&self, key: S) -> Option<&Val> {
71 self.direct_ref().get(key)
72 }
73}
74
75impl PartialEq for Val {
76 fn eq(&self, other: &Self) -> bool {
77 self.direct_ref() == other.direct_ref()
78 }
79}
80
81impl Eq for Val {}
82
83impl PartialOrd for Val {
84 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
85 self.direct_ref().partial_cmp(&other.direct_ref())
86 }
87}
88
89impl Ord for Val {
90 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
91 self.direct_ref().cmp(&other.direct_ref())
92 }
93}
94
95impl Debug for Val {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 self.direct_ref().fmt(f)
98 }
99}
100
101impl Clone for Val {
102 #[inline]
103 fn clone(&self) -> Self {
104 match self.direct_ref() {
105 ValRef::Null => ValE::Null,
106 ValRef::Bool(b) => ValE::Bool(b),
107 ValRef::Number(n) => ValE::Number(n),
108 ValRef::String(s) => ValE::str(s),
109 ValRef::Array(a) => ValE::Array(SlimBoxedSlice::from_vec(a.to_vec())),
110 ValRef::Object(o) => ValE::Object(Map::clone_from_ref(&o)),
111 }
112 .into()
113 }
114}
115
116impl Hash for Val {
117 #[inline]
118 fn hash<H: Hasher>(&self, state: &mut H) {
119 self.direct_ref().hash(state)
120 }
121}
122
123impl Index<usize> for Val {
124 type Output = Val;
125
126 #[inline]
127 fn index(&self, index: usize) -> &Self::Output {
128 match self.direct_ref() {
129 ValRef::Array(a) => &a[index],
130 _ => panic!("Tried to index into Val that is not an array"),
131 }
132 }
133}
134
135impl DeepSizeOf for Val {
136 fn deep_size_of_children(&self, context: &mut deepsize::Context) -> usize {
137 let unsafe_clone = Val(self.0).into();
138 let size = match &unsafe_clone {
139 ValE::Bool(_) => 8,
140 ValE::Null => 8,
141 ValE::Number(_) => 8,
142 ValE::ShortString(_) => 8,
143 ValE::LongString(s) => s.deep_size_of_children(context),
144 ValE::Array(a) => a.deep_size_of_children(context),
145 ValE::Object(o) => o.deep_size_of_children(context),
146 };
147 std::mem::forget(unsafe_clone);
148 size
149 }
150}