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