Skip to main content

looking_glass/
value.rs

1use crate::*;
2pub use bytes::Bytes;
3pub use smol_str::SmolStr;
4
5use std::{collections::HashMap, hash::Hash};
6
7/// A container for a type-erased value.
8///
9/// Value is, in essence, a smart-pointer that can hold any reflected type. It is slightly larger than a standard fat-pointer, since it contains
10/// metadata about the type it contains.
11#[derive(Clone)]
12pub struct Value<'val, 'ty>(pub(crate) ValueInner<'val, 'ty>)
13where
14    'ty: 'val;
15
16#[derive(Clone)]
17pub(crate) enum ValueInner<'val, 'ty>
18where
19    'ty: 'val,
20{
21    U64(u64),
22    U32(u32),
23    U16(u16),
24    U8(u8),
25    I64(i64),
26    I32(i32),
27    I16(i16),
28    I8(i8),
29    F32(f32),
30    F64(f64),
31    Bool(bool),
32    String(&'val String),
33    Str(&'val str),
34    Vec(&'val (dyn VecInstance<'ty> + 'ty)),
35    HashMap(&'val (dyn HashMapInstance<'ty> + 'ty)),
36    Struct(&'val (dyn StructInstance<'ty> + 'ty)),
37    Enum(&'val (dyn EnumInstance<'ty> + 'ty)),
38    Bytes(&'val Bytes),
39    Option(&'val (dyn OptionInstance<'ty> + 'ty)),
40}
41
42impl<'val, 'ty> Value<'val, 'ty> {
43    /// Creates a [`Value`] from a reflected vec
44    pub fn from_vec(s: &'val (dyn VecInstance<'ty> + 'ty)) -> Value<'val, 'ty> {
45        Value(ValueInner::Vec(s))
46    }
47
48    /// Creates a [`Value`] from a reflected hashmap
49    pub fn from_hashmap(s: &'val (dyn HashMapInstance<'ty> + 'ty)) -> Value<'val, 'ty> {
50        Value(ValueInner::HashMap(s))
51    }
52
53    /// Creates a [`Value`] from a reflected struct
54    pub fn from_struct(s: &'val (dyn StructInstance<'ty> + 'ty)) -> Value<'val, 'ty> {
55        Value(ValueInner::Struct(s))
56    }
57
58    /// Creates a [`Value`] from a reflected enum
59    pub fn from_enum(s: &'val (dyn EnumInstance<'ty> + 'ty)) -> Value<'val, 'ty> {
60        Value(ValueInner::Enum(s))
61    }
62
63    /// Creates a [`Value`] from a reflected option
64    pub fn from_option(s: &'val (dyn OptionInstance<'ty> + 'ty)) -> Value<'val, 'ty> {
65        Value(ValueInner::Option(s))
66    }
67
68    /// Borrows the value as an underlying type. This will return `None`,
69    /// when the runtime type-check fails
70    pub fn borrow<'b, T: FromValue<'val, 'ty>>(&'b self) -> Option<T>
71    where
72        'val: 'b,
73        'ty: 'b,
74    {
75        T::from_value(self)
76    }
77
78    /// Consumes the `Value` and returns the internal `T`.
79    ///
80    /// This only works for types that implement [`FromValue`], which are generally primitives
81    /// that implement `Copy`.
82    pub fn into<T: FromValue<'val, 'ty> + 'ty>(self) -> Option<T> {
83        T::from_value(&self)
84    }
85
86    /// Attempts to cast `Value` to a [`VecInstance`]
87    pub fn as_reflected_vec(&self) -> Option<&'val (dyn VecInstance<'ty> + 'ty)> {
88        match self.0 {
89            ValueInner::Vec(v) => Some(v),
90            _ => None,
91        }
92    }
93
94    /// Attempts to cast `Value` to a [`StructInstance`]
95    pub fn as_reflected_struct(&self) -> Option<&'val (dyn StructInstance<'ty> + 'ty)> {
96        match self.0 {
97            ValueInner::Struct(v) => Some(v),
98            _ => None,
99        }
100    }
101
102    /// Attempts to cast `Value` to a [`EnumInstance`]
103    pub fn as_reflected_enum(&'val self) -> Option<&(dyn EnumInstance<'ty> + 'ty)> {
104        match self.0 {
105            ValueInner::Enum(v) => Some(v),
106            _ => None,
107        }
108    }
109
110    /// Attempts to cast `Value` to a [`OptionInstance`]
111    pub fn as_reflected_option(&'val self) -> Option<&(dyn OptionInstance<'ty> + 'ty)> {
112        match self.0 {
113            ValueInner::Option(v) => Some(v),
114            _ => None,
115        }
116    }
117
118    /// Attempts to cast `Value` to a [`HashMapInstance`]
119    pub fn as_reflected_hashmap(&self) -> Option<&'val (dyn HashMapInstance<'ty> + 'ty)> {
120        match self.0 {
121            ValueInner::HashMap(v) => Some(v),
122            _ => None,
123        }
124    }
125
126    /// Clones the underlying value, and returns a [`OwnedValue`]
127    pub fn to_owned(&self) -> OwnedValue<'ty> {
128        match self.0 {
129            ValueInner::U64(u) => OwnedValue::U64(u),
130            ValueInner::U32(u) => OwnedValue::U32(u),
131            ValueInner::U16(u) => OwnedValue::U16(u),
132            ValueInner::U8(u) => OwnedValue::U8(u),
133            ValueInner::I64(u) => OwnedValue::I64(u),
134            ValueInner::I32(u) => OwnedValue::I32(u),
135            ValueInner::I16(u) => OwnedValue::I16(u),
136            ValueInner::I8(u) => OwnedValue::I8(u),
137            ValueInner::F32(u) => OwnedValue::F32(u),
138            ValueInner::F64(u) => OwnedValue::F64(u),
139            ValueInner::Bool(u) => OwnedValue::Bool(u),
140            ValueInner::String(s) => OwnedValue::String(s.clone()),
141            ValueInner::Str(s) => OwnedValue::String(s.to_string()),
142            ValueInner::Vec(v) => OwnedValue::Vec(v.boxed_clone()),
143            ValueInner::HashMap(v) => OwnedValue::HashMap(v.boxed_clone()),
144            ValueInner::Struct(s) => OwnedValue::Struct(s.boxed_clone()),
145            ValueInner::Enum(e) => OwnedValue::Enum(e.boxed_clone()),
146            ValueInner::Bytes(b) => OwnedValue::Bytes(b.clone()),
147            ValueInner::Option(o) => OwnedValue::Option(o.boxed_clone()),
148        }
149    }
150
151    /// Attempts to has the [`Value`], only returning a value if the underlying type is hashable
152    pub fn try_hash<H: std::hash::Hasher>(&self, mut hasher: H) -> Option<u64> {
153        match self.0 {
154            ValueInner::U64(x) => x.hash(&mut hasher),
155            ValueInner::U32(x) => x.hash(&mut hasher),
156            ValueInner::U16(x) => x.hash(&mut hasher),
157            ValueInner::U8(x) => x.hash(&mut hasher),
158            ValueInner::I64(x) => x.hash(&mut hasher),
159            ValueInner::I32(x) => x.hash(&mut hasher),
160            ValueInner::I16(x) => x.hash(&mut hasher),
161            ValueInner::I8(x) => x.hash(&mut hasher),
162            ValueInner::Bool(x) => x.hash(&mut hasher),
163            ValueInner::String(x) => x.hash(&mut hasher),
164            ValueInner::Str(x) => x.hash(&mut hasher),
165            ValueInner::Bytes(x) => x.hash(&mut hasher),
166            _ => return None,
167        };
168        Some(hasher.finish())
169    }
170
171    /// Checks if two `Values` are equal.
172    ///
173    /// This is slower than the implementations in [`PartialEq`],
174    /// but it works with `Values` of different lifetimes.
175    /// It is slower, because it is implemented using reflection calls,
176    /// rather than downcasting.
177    pub fn slow_eq<'c, 'd>(&self, r: &Value<'c, 'd>) -> bool {
178        match (&self.0, &r.0) {
179            (ValueInner::U64(l), ValueInner::U64(r)) => l == r,
180            (ValueInner::U32(l), ValueInner::U32(r)) => l == r,
181            (ValueInner::U16(l), ValueInner::U16(r)) => l == r,
182            (ValueInner::U8(l), ValueInner::U8(r)) => l == r,
183            (ValueInner::I64(l), ValueInner::I64(r)) => l == r,
184            (ValueInner::I32(l), ValueInner::I32(r)) => l == r,
185            (ValueInner::I16(l), ValueInner::I16(r)) => l == r,
186            (ValueInner::I8(l), ValueInner::I8(r)) => l == r,
187            (ValueInner::F32(l), ValueInner::F32(r)) => l == r,
188            (ValueInner::F64(l), ValueInner::F64(r)) => l == r,
189            (ValueInner::Bool(l), ValueInner::Bool(r)) => l == r,
190            (ValueInner::String(l), ValueInner::String(r)) => l == r,
191            (ValueInner::Str(l), ValueInner::Str(r)) => l == r,
192            (ValueInner::String(l), ValueInner::Str(r))
193            | (ValueInner::Str(r), ValueInner::String(l)) => l == r,
194            (ValueInner::Bytes(l), ValueInner::Bytes(r)) => l == r,
195            (ValueInner::Struct(l), ValueInner::Struct(r)) => {
196                match_map_fields(l.values(), r.values())
197            }
198            (ValueInner::HashMap(l), ValueInner::HashMap(r)) => {
199                match_raw_map_fields(l.values(), r.values())
200            }
201            (ValueInner::Vec(l), ValueInner::Vec(r)) => match_vec_fields(l.values(), r.values()),
202            (ValueInner::Enum(l), ValueInner::Enum(r)) => match (l.field(), r.field()) {
203                (EnumField::Unit(l), EnumField::Unit(r)) => l == r,
204                (
205                    EnumField::Tuple {
206                        name: l_name,
207                        fields: l_fields,
208                    },
209                    EnumField::Tuple {
210                        name: r_name,
211                        fields: r_fields,
212                    },
213                ) => {
214                    if l_name == r_name {
215                        match_vec_fields(l_fields, r_fields)
216                    } else {
217                        false
218                    }
219                }
220                (
221                    EnumField::Struct {
222                        name: l_name,
223                        fields: l_fields,
224                    },
225                    EnumField::Struct {
226                        name: r_name,
227                        fields: r_fields,
228                    },
229                ) => {
230                    if l_name == r_name {
231                        match_map_fields(l_fields, r_fields)
232                    } else {
233                        false
234                    }
235                }
236                _ => false,
237            },
238            _ => false,
239        }
240    }
241}
242
243impl<'val, 'ty> From<&'val Bytes> for Value<'val, 'ty> {
244    fn from(bytes: &'val Bytes) -> Self {
245        Self(ValueInner::Bytes(bytes))
246    }
247}
248
249fn match_vec_fields(l_fields: Vec<CowValue<'_, '_>>, r_fields: Vec<CowValue<'_, '_>>) -> bool {
250    if l_fields.len() != r_fields.len() {
251        return false;
252    }
253    for (i, l_val) in l_fields.iter().enumerate() {
254        if let Some(r_val) = r_fields.get(i) {
255            if !l_val.slow_eq(r_val) {
256                return false;
257            }
258        } else {
259            return false;
260        }
261    }
262    true
263}
264
265fn match_raw_map_fields(
266    l_fields: HashMap<String, CowValue<'_, '_>>,
267    r_fields: HashMap<String, CowValue<'_, '_>>,
268) -> bool {
269    if l_fields.len() != r_fields.len() {
270        return false;
271    }
272
273    l_fields.iter().all(|(field, l_val)| {
274        r_fields.get(field).map_or(false, |r_val| l_val.slow_eq(r_val))
275    })
276}
277
278fn match_map_fields(
279    l_fields: HashMap<SmolStr, CowValue<'_, '_>>,
280    r_fields: HashMap<SmolStr, CowValue<'_, '_>>,
281) -> bool {
282    if l_fields.len() != r_fields.len() {
283        return false;
284    }
285    for (field, l_val) in &l_fields {
286        if let Some(r_val) = r_fields.get(field) {
287            if !l_val.slow_eq(r_val) {
288                return false;
289            }
290        } else {
291            return false;
292        }
293    }
294    true
295}
296
297impl std::fmt::Debug for Value<'_, '_> {
298    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
299        match self.0 {
300            ValueInner::U64(x) => std::fmt::Debug::fmt(&x, f),
301            ValueInner::U32(x) => std::fmt::Debug::fmt(&x, f),
302            ValueInner::U16(x) => std::fmt::Debug::fmt(&x, f),
303            ValueInner::U8(x) => std::fmt::Debug::fmt(&x, f),
304            ValueInner::I64(x) => std::fmt::Debug::fmt(&x, f),
305            ValueInner::I32(x) => std::fmt::Debug::fmt(&x, f),
306            ValueInner::I16(x) => std::fmt::Debug::fmt(&x, f),
307            ValueInner::I8(x) => std::fmt::Debug::fmt(&x, f),
308            ValueInner::F32(x) => std::fmt::Debug::fmt(&x, f),
309            ValueInner::F64(x) => std::fmt::Debug::fmt(&x, f),
310            ValueInner::Bool(x) => std::fmt::Debug::fmt(&x, f),
311            ValueInner::String(x) => std::fmt::Debug::fmt(&x, f),
312            ValueInner::Str(x) => std::fmt::Debug::fmt(&x, f),
313            ValueInner::Vec(x) => std::fmt::Debug::fmt(&x, f),
314            ValueInner::HashMap(x) => std::fmt::Debug::fmt(&x, f),
315            ValueInner::Struct(x) => std::fmt::Debug::fmt(&x, f),
316            ValueInner::Enum(x) => std::fmt::Debug::fmt(&x, f),
317            ValueInner::Bytes(x) => std::fmt::Debug::fmt(&x, f),
318            ValueInner::Option(x) => std::fmt::Debug::fmt(&x, f),
319        }
320    }
321}
322
323impl PartialEq for Value<'_, '_> {
324    fn eq(&self, other: &Self) -> bool {
325        match (&self.0, &other.0) {
326            (ValueInner::U64(l), ValueInner::U64(r)) => l == r,
327            (ValueInner::U32(l), ValueInner::U32(r)) => l == r,
328            (ValueInner::U16(l), ValueInner::U16(r)) => l == r,
329            (ValueInner::U8(l), ValueInner::U8(r)) => l == r,
330            (ValueInner::I64(l), ValueInner::I64(r)) => l == r,
331            (ValueInner::I32(l), ValueInner::I32(r)) => l == r,
332            (ValueInner::I16(l), ValueInner::I16(r)) => l == r,
333            (ValueInner::I8(l), ValueInner::I8(r)) => l == r,
334            (ValueInner::F32(l), ValueInner::F32(r)) => l == r,
335            (ValueInner::F64(l), ValueInner::F64(r)) => l == r,
336            (ValueInner::Bool(l), ValueInner::Bool(r)) => l == r,
337            (ValueInner::String(l), ValueInner::String(r)) => l == r,
338            (ValueInner::Str(st), ValueInner::String(s))
339            | (ValueInner::String(s), ValueInner::Str(st)) => st == s,
340            (ValueInner::Str(l), ValueInner::Str(r)) => l == r,
341            (ValueInner::Vec(l), ValueInner::Vec(r)) => l == r,
342            (ValueInner::Bytes(l), ValueInner::Bytes(r)) => l == r,
343            (ValueInner::Struct(l), ValueInner::Struct(r)) => l == r,
344            (ValueInner::Option(l), ValueInner::Option(r)) => l == r,
345            (ValueInner::Enum(l), ValueInner::Enum(r)) => l == r,
346            (ValueInner::HashMap(l), ValueInner::HashMap(r)) => l == r,
347            (_, _) => false,
348        }
349    }
350}