1use std::collections::HashMap;
2
3use ordered_float::OrderedFloat;
4
5use crate::{array::Array, map::Map, CowBytes, CowStr, IntoStatic, MerdeError, ValueType};
6
7#[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 i8 => I64,
62 i16 => I64,
63 i32 => I64,
64 i64 => I64,
65 u8 => U64,
67 u16 => U64,
68 u32 => U64,
69 u64 => U64,
70 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}