merde_core/
value.rs

1use std::collections::HashMap;
2
3use ordered_float::OrderedFloat;
4
5use crate::{array::Array, map::Map, CowBytes, CowStr, IntoStatic, MerdeError, ValueType};
6
7/// Think [`serde_json::Value`](https://docs.rs/serde_json/1.0.128/serde_json/enum.Value.html), but with a small string optimization,
8/// copy-on-write strings, etc. Might include other value types later.
9#[derive(Debug, PartialEq, Eq, Hash, Clone)]
10pub enum Value<'s> {
11    I64(i64),
12    U64(u64),
13    Float(OrderedFloat<f64>),
14    Str(CowStr<'s>),
15    Bytes(CowBytes<'s>),
16    Null,
17    Bool(bool),
18    Array(Array<'s>),
19    Map(Map<'s>),
20}
21
22impl IntoStatic for Value<'_> {
23    type Output = Value<'static>;
24
25    #[inline(always)]
26    fn into_static(self) -> <Self as IntoStatic>::Output {
27        match self {
28            Value::I64(i) => Value::I64(i),
29            Value::U64(u) => Value::U64(u),
30            Value::Float(f) => Value::Float(f),
31            Value::Str(s) => Value::Str(s.into_static()),
32            Value::Bytes(b) => Value::Bytes(b.into_static()),
33            Value::Null => Value::Null,
34            Value::Bool(b) => Value::Bool(b),
35            Value::Array(arr) => Value::Array(arr.into_static()),
36            Value::Map(map) => Value::Map(map.into_static()),
37        }
38    }
39}
40
41macro_rules! impl_from_for_value {
42    ($ty:ty => $variant:ident, $($rest:tt)*) => {
43        impl_from_for_value!($ty => $variant);
44        impl_from_for_value!($($rest)*);
45    };
46
47    ($ty:ty => $variant:ident) => {
48        impl<'s> From<$ty> for Value<'s> {
49            fn from(v: $ty) -> Self {
50                Value::$variant(v.into())
51            }
52        }
53    };
54
55    (,) => {};
56    () => {};
57}
58
59impl_from_for_value! {
60    // signed
61    i8 => I64,
62    i16 => I64,
63    i32 => I64,
64    i64 => I64,
65    // unsigned
66    u8 => U64,
67    u16 => U64,
68    u32 => U64,
69    u64 => U64,
70    // misc.
71    CowStr<'s> => Str,
72    CowBytes<'s> => Bytes,
73}
74
75impl From<f32> for Value<'_> {
76    fn from(v: f32) -> Self {
77        Value::Float((v as f64).into())
78    }
79}
80
81impl From<f64> for Value<'_> {
82    fn from(v: f64) -> Self {
83        Value::Float(v.into())
84    }
85}
86
87impl<'s> From<&'s str> for Value<'s> {
88    fn from(v: &'s str) -> Self {
89        Value::Str(v.into())
90    }
91}
92
93impl From<String> for Value<'_> {
94    fn from(v: String) -> Self {
95        Value::Str(v.into())
96    }
97}
98
99impl<'s> From<&'s String> for Value<'s> {
100    fn from(v: &'s String) -> Self {
101        Value::Str(v.as_str().into())
102    }
103}
104
105impl From<()> for Value<'_> {
106    fn from(_: ()) -> Self {
107        Value::Null
108    }
109}
110
111impl From<bool> for Value<'_> {
112    fn from(v: bool) -> Self {
113        Value::Bool(v)
114    }
115}
116
117impl<'s> From<Array<'s>> for Value<'s> {
118    fn from(v: Array<'s>) -> Self {
119        Value::Array(v)
120    }
121}
122
123impl<'s> From<Map<'s>> for Value<'s> {
124    fn from(v: Map<'s>) -> Self {
125        Value::Map(v)
126    }
127}
128
129impl<'s> From<Vec<Value<'s>>> for Value<'s> {
130    fn from(v: Vec<Value<'s>>) -> Self {
131        Value::Array(Array(v))
132    }
133}
134
135impl<'s> From<HashMap<CowStr<'s>, Value<'s>>> for Value<'s> {
136    fn from(v: HashMap<CowStr<'s>, Value<'s>>) -> Self {
137        Value::Map(Map(v))
138    }
139}
140
141impl<'s> Value<'s> {
142    #[inline(always)]
143    pub fn as_map(&self) -> Result<&Map<'s>, MerdeError<'static>> {
144        match self {
145            Value::Map(obj) => Ok(obj),
146            _ => Err(MerdeError::MismatchedType {
147                expected: ValueType::Map,
148                found: self.value_type(),
149            }),
150        }
151    }
152
153    #[inline(always)]
154    pub fn into_map(self) -> Result<Map<'s>, MerdeError<'static>> {
155        match self {
156            Value::Map(obj) => Ok(obj),
157            _ => Err(MerdeError::MismatchedType {
158                expected: ValueType::Map,
159                found: self.value_type(),
160            }),
161        }
162    }
163
164    #[inline(always)]
165    pub fn as_array(&self) -> Result<&Array<'s>, MerdeError<'static>> {
166        match self {
167            Value::Array(arr) => Ok(arr),
168            _ => Err(MerdeError::MismatchedType {
169                expected: ValueType::Array,
170                found: self.value_type(),
171            }),
172        }
173    }
174
175    #[inline(always)]
176    pub fn into_array(self) -> Result<Array<'s>, MerdeError<'static>> {
177        match self {
178            Value::Array(arr) => Ok(arr),
179            _ => Err(MerdeError::MismatchedType {
180                expected: ValueType::Array,
181                found: self.value_type(),
182            }),
183        }
184    }
185
186    #[inline(always)]
187    pub fn as_str(&self) -> Result<&CowStr<'s>, MerdeError<'static>> {
188        match self {
189            Value::Str(s) => Ok(s),
190            _ => Err(MerdeError::MismatchedType {
191                expected: ValueType::String,
192                found: self.value_type(),
193            }),
194        }
195    }
196
197    #[inline(always)]
198    pub fn into_str(self) -> Result<CowStr<'s>, MerdeError<'static>> {
199        match self {
200            Value::Str(s) => Ok(s),
201            _ => Err(MerdeError::MismatchedType {
202                expected: ValueType::String,
203                found: self.value_type(),
204            }),
205        }
206    }
207
208    #[inline(always)]
209    pub fn as_bytes(&self) -> Result<&CowBytes<'s>, MerdeError<'static>> {
210        match self {
211            Value::Bytes(b) => Ok(b),
212            _ => Err(MerdeError::MismatchedType {
213                expected: ValueType::Bytes,
214                found: self.value_type(),
215            }),
216        }
217    }
218
219    #[inline(always)]
220    pub fn into_bytes(self) -> Result<CowBytes<'s>, MerdeError<'static>> {
221        match self {
222            Value::Bytes(b) => Ok(b),
223            _ => Err(MerdeError::MismatchedType {
224                expected: ValueType::Bytes,
225                found: self.value_type(),
226            }),
227        }
228    }
229
230    #[inline(always)]
231    pub fn as_i64(&self) -> Result<i64, MerdeError<'static>> {
232        match self {
233            Value::I64(n) => Ok(*n),
234            Value::U64(n) if *n <= i64::MAX as u64 => Ok(*n as i64),
235            _ => Err(MerdeError::MismatchedType {
236                expected: ValueType::I64,
237                found: self.value_type(),
238            }),
239        }
240    }
241
242    #[inline(always)]
243    pub fn as_u64(&self) -> Result<u64, MerdeError<'static>> {
244        match self {
245            Value::U64(n) => Ok(*n),
246            Value::I64(n) => Ok((*n).try_into().map_err(|_| MerdeError::OutOfRange)?),
247            _ => Err(MerdeError::MismatchedType {
248                expected: ValueType::U64,
249                found: self.value_type(),
250            }),
251        }
252    }
253
254    #[inline(always)]
255    pub fn as_f64(&self) -> Result<f64, MerdeError<'static>> {
256        match self {
257            Value::Float(n) => Ok(n.into_inner()),
258            _ => Err(MerdeError::MismatchedType {
259                expected: ValueType::Float,
260                found: self.value_type(),
261            }),
262        }
263    }
264}