mirror_mirror/
key_path.rs

1use alloc::borrow::ToOwned;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5use core::iter::FusedIterator;
6use core::iter::Peekable;
7
8use crate::enum_::VariantKind;
9use crate::type_info::TypeAtPath;
10use crate::Reflect;
11use crate::ReflectMut;
12use crate::ReflectRef;
13use crate::Value;
14
15pub trait GetPath {
16    fn at(&self, key_path: &KeyPath) -> Option<&dyn Reflect>;
17
18    fn get_at<T>(&self, key_path: &KeyPath) -> Option<&T>
19    where
20        T: Reflect,
21    {
22        self.at(key_path)?.downcast_ref()
23    }
24
25    fn at_mut(&mut self, key_path: &KeyPath) -> Option<&mut dyn Reflect>;
26
27    fn get_at_mut<T>(&mut self, key_path: &KeyPath) -> Option<&mut T>
28    where
29        T: Reflect,
30    {
31        self.at_mut(key_path)?.downcast_mut()
32    }
33}
34
35pub trait GetTypePath<'a> {
36    fn type_at(self, key_path: &KeyPath) -> Option<TypeAtPath<'a>>;
37}
38
39impl<R> GetPath for R
40where
41    R: Reflect + ?Sized,
42{
43    fn at(&self, key_path: &KeyPath) -> Option<&dyn Reflect> {
44        fn go<'a, 'b, R>(
45            value: &'a R,
46            mut stack: Peekable<impl Iterator<Item = &'b Key>>,
47        ) -> Option<&'a dyn Reflect>
48        where
49            R: Reflect + ?Sized,
50        {
51            let head = stack.next()?;
52
53            let value_at_key = match head {
54                // .foo
55                Key::Field(NamedOrNumbered::Named(key)) => match value.reflect_ref() {
56                    ReflectRef::Struct(inner) => inner.field(key)?,
57                    ReflectRef::Enum(inner) => match inner.variant_kind() {
58                        VariantKind::Struct => inner.field(key)?,
59                        VariantKind::Tuple | VariantKind::Unit => return None,
60                    },
61                    ReflectRef::TupleStruct(_)
62                    | ReflectRef::Tuple(_)
63                    | ReflectRef::Array(_)
64                    | ReflectRef::List(_)
65                    | ReflectRef::Map(_)
66                    | ReflectRef::Scalar(_)
67                    | ReflectRef::Opaque(_) => return None,
68                },
69                // .0
70                Key::Field(NamedOrNumbered::Numbered(index)) => match value.reflect_ref() {
71                    ReflectRef::TupleStruct(inner) => inner.field_at(*index)?,
72                    ReflectRef::Tuple(inner) => inner.field_at(*index)?,
73                    ReflectRef::Enum(inner) => match inner.variant_kind() {
74                        VariantKind::Tuple => inner.field_at(*index)?,
75                        VariantKind::Struct | VariantKind::Unit => return None,
76                    },
77                    ReflectRef::Map(_)
78                    | ReflectRef::Struct(_)
79                    | ReflectRef::Array(_)
80                    | ReflectRef::List(_)
81                    | ReflectRef::Scalar(_)
82                    | ReflectRef::Opaque(_) => return None,
83                },
84                // ["foo"] or [0]
85                Key::Get(key) => match value.reflect_ref() {
86                    ReflectRef::Map(inner) => inner.get(key)?,
87                    ReflectRef::Array(inner) => inner.get(value_to_usize(key)?)?,
88                    ReflectRef::List(inner) => inner.get(value_to_usize(key)?)?,
89                    ReflectRef::Struct(_)
90                    | ReflectRef::TupleStruct(_)
91                    | ReflectRef::Tuple(_)
92                    | ReflectRef::Enum(_)
93                    | ReflectRef::Scalar(_)
94                    | ReflectRef::Opaque(_) => return None,
95                },
96                // ::Some
97                Key::Variant(variant) => match value.reflect_ref() {
98                    ReflectRef::Enum(enum_) => {
99                        if enum_.variant_name() == variant {
100                            enum_.as_reflect()
101                        } else {
102                            return None;
103                        }
104                    }
105                    ReflectRef::Struct(_)
106                    | ReflectRef::TupleStruct(_)
107                    | ReflectRef::Tuple(_)
108                    | ReflectRef::List(_)
109                    | ReflectRef::Array(_)
110                    | ReflectRef::Map(_)
111                    | ReflectRef::Opaque(_)
112                    | ReflectRef::Scalar(_) => return None,
113                },
114            };
115
116            if stack.peek().is_none() {
117                Some(value_at_key)
118            } else {
119                go(value_at_key, stack)
120            }
121        }
122
123        if key_path.is_empty() {
124            return Some(self.as_reflect());
125        }
126
127        go(self, key_path.path.iter().peekable())
128    }
129
130    fn at_mut(&mut self, key_path: &KeyPath) -> Option<&mut dyn Reflect> {
131        fn go<'a, 'b, R>(
132            value: &'a mut R,
133            mut stack: Peekable<impl Iterator<Item = &'b Key>>,
134        ) -> Option<&'a mut dyn Reflect>
135        where
136            R: Reflect + ?Sized,
137        {
138            let head = stack.next()?;
139
140            let value_at_key = match head {
141                // .foo
142                Key::Field(NamedOrNumbered::Named(key)) => match value.reflect_mut() {
143                    ReflectMut::Struct(inner) => inner.field_mut(key)?,
144                    ReflectMut::Enum(inner) => match inner.variant_kind() {
145                        VariantKind::Struct => inner.field_mut(key)?,
146                        VariantKind::Tuple | VariantKind::Unit => return None,
147                    },
148                    ReflectMut::TupleStruct(_)
149                    | ReflectMut::Tuple(_)
150                    | ReflectMut::Array(_)
151                    | ReflectMut::List(_)
152                    | ReflectMut::Map(_)
153                    | ReflectMut::Scalar(_)
154                    | ReflectMut::Opaque(_) => return None,
155                },
156                // .0
157                Key::Field(NamedOrNumbered::Numbered(index)) => match value.reflect_mut() {
158                    ReflectMut::TupleStruct(inner) => inner.field_at_mut(*index)?,
159                    ReflectMut::Tuple(inner) => inner.field_at_mut(*index)?,
160                    ReflectMut::Enum(inner) => match inner.variant_kind() {
161                        VariantKind::Tuple => inner.field_at_mut(*index)?,
162                        VariantKind::Struct | VariantKind::Unit => return None,
163                    },
164                    ReflectMut::Map(_)
165                    | ReflectMut::Struct(_)
166                    | ReflectMut::Array(_)
167                    | ReflectMut::List(_)
168                    | ReflectMut::Scalar(_)
169                    | ReflectMut::Opaque(_) => return None,
170                },
171                // ["foo"] or [0]
172                Key::Get(key) => match value.reflect_mut() {
173                    ReflectMut::Array(inner) => inner.get_mut(value_to_usize(key)?)?,
174                    ReflectMut::List(inner) => inner.get_mut(value_to_usize(key)?)?,
175                    ReflectMut::Map(inner) => inner.get_mut(key)?,
176                    ReflectMut::Struct(_)
177                    | ReflectMut::TupleStruct(_)
178                    | ReflectMut::Tuple(_)
179                    | ReflectMut::Enum(_)
180                    | ReflectMut::Scalar(_)
181                    | ReflectMut::Opaque(_) => return None,
182                },
183                // ::Some
184                Key::Variant(variant) => match value.reflect_mut() {
185                    ReflectMut::Enum(enum_) => {
186                        if enum_.variant_name() == variant {
187                            enum_.as_reflect_mut()
188                        } else {
189                            return None;
190                        }
191                    }
192                    ReflectMut::Struct(_)
193                    | ReflectMut::TupleStruct(_)
194                    | ReflectMut::Tuple(_)
195                    | ReflectMut::List(_)
196                    | ReflectMut::Array(_)
197                    | ReflectMut::Map(_)
198                    | ReflectMut::Opaque(_)
199                    | ReflectMut::Scalar(_) => return None,
200                },
201            };
202
203            if stack.peek().is_none() {
204                Some(value_at_key)
205            } else {
206                go(value_at_key, stack)
207            }
208        }
209
210        if key_path.is_empty() {
211            return Some(self.as_reflect_mut());
212        }
213
214        go(self, key_path.path.iter().peekable())
215    }
216}
217
218#[derive(Debug, Clone, Default, Eq, PartialEq, Hash)]
219#[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))]
220#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
221pub struct KeyPath {
222    pub(crate) path: Vec<Key>,
223}
224
225impl KeyPath {
226    pub fn field(mut self, field: impl IntoKeyOrIndex) -> Self {
227        self.push_field(field);
228        self
229    }
230
231    pub fn push_field(&mut self, field: impl IntoKeyOrIndex) {
232        self.push(Key::Field(field.into_key_or_index()));
233    }
234
235    pub fn get(mut self, field: impl Into<Value>) -> Self {
236        self.push_get(field);
237        self
238    }
239
240    pub fn push_get(&mut self, field: impl Into<Value>) {
241        self.push(Key::Get(field.into()))
242    }
243
244    pub fn variant(mut self, variant: impl Into<String>) -> Self {
245        self.push_variant(variant);
246        self
247    }
248
249    pub fn push_variant(&mut self, variant: impl Into<String>) {
250        self.push(Key::Variant(variant.into()));
251    }
252
253    pub fn push(&mut self, key: Key) {
254        self.path.push(key);
255    }
256
257    pub fn len(&self) -> usize {
258        self.path.len()
259    }
260
261    pub fn is_empty(&self) -> bool {
262        self.path.is_empty()
263    }
264
265    pub fn pop(&mut self) {
266        self.path.pop();
267    }
268
269    pub fn iter(&self) -> Iter<'_> {
270        self.into_iter()
271    }
272
273    pub fn breadcrumbs(&self) -> Breadcrumbs<'_> {
274        Breadcrumbs {
275            key_path: self,
276            index: 1,
277        }
278    }
279}
280
281impl From<Key> for KeyPath {
282    fn from(key: Key) -> Self {
283        let mut key_path = KeyPath::default();
284        key_path.push(key);
285        key_path
286    }
287}
288
289impl Extend<Key> for KeyPath {
290    fn extend<T>(&mut self, iter: T)
291    where
292        T: IntoIterator<Item = Key>,
293    {
294        self.path.extend(iter);
295    }
296}
297
298impl IntoIterator for KeyPath {
299    type Item = Key;
300    type IntoIter = IntoIter;
301
302    fn into_iter(self) -> Self::IntoIter {
303        IntoIter(self.path.into_iter())
304    }
305}
306
307#[derive(Debug)]
308pub struct IntoIter(alloc::vec::IntoIter<Key>);
309
310impl Iterator for IntoIter {
311    type Item = Key;
312
313    fn next(&mut self) -> Option<Self::Item> {
314        self.0.next()
315    }
316}
317
318impl DoubleEndedIterator for IntoIter {
319    fn next_back(&mut self) -> Option<Self::Item> {
320        self.0.next_back()
321    }
322}
323
324impl ExactSizeIterator for IntoIter {
325    fn len(&self) -> usize {
326        self.0.len()
327    }
328}
329
330impl FusedIterator for IntoIter {}
331
332impl<'a> IntoIterator for &'a KeyPath {
333    type Item = &'a Key;
334    type IntoIter = Iter<'a>;
335
336    fn into_iter(self) -> Self::IntoIter {
337        Iter(self.path.iter())
338    }
339}
340
341#[derive(Debug)]
342pub struct Iter<'a>(alloc::slice::Iter<'a, Key>);
343
344impl<'a> Iterator for Iter<'a> {
345    type Item = &'a Key;
346
347    fn next(&mut self) -> Option<Self::Item> {
348        self.0.next()
349    }
350}
351
352impl<'a> DoubleEndedIterator for Iter<'a> {
353    fn next_back(&mut self) -> Option<Self::Item> {
354        self.0.next_back()
355    }
356}
357
358impl<'a> ExactSizeIterator for Iter<'a> {
359    fn len(&self) -> usize {
360        self.0.len()
361    }
362}
363
364impl<'a> FusedIterator for Iter<'a> {}
365
366mod private {
367    use super::*;
368
369    pub trait Sealed {}
370    impl Sealed for &str {}
371    impl Sealed for &String {}
372    impl Sealed for String {}
373    impl Sealed for usize {}
374}
375
376#[derive(Debug, Clone, Eq, PartialEq, Hash)]
377#[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))]
378#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
379pub enum Key {
380    Field(NamedOrNumbered),
381    Get(Value),
382    Variant(String),
383}
384
385impl Key {
386    /// Create a `Key` that'll access a named field of a struct.
387    pub fn named_field(name: impl Into<String>) -> Self {
388        Self::Field(NamedOrNumbered::Named(name.into()))
389    }
390
391    /// Create a `Key` that'll access a numbered field of a tuple struct or tuple.
392    pub fn numbered_field(index: usize) -> Self {
393        Self::Field(NamedOrNumbered::Numbered(index))
394    }
395
396    /// Create a `Key` that'll access an element in a list, array, or map.
397    pub fn get(value: impl Into<Value>) -> Self {
398        Self::Get(value.into())
399    }
400
401    /// Create a `Key` that'll access an enum variant.
402    pub fn variant(name: impl Into<String>) -> Self {
403        Self::Variant(name.into())
404    }
405}
406
407impl fmt::Display for Key {
408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409        match self {
410            Key::Field(key) => write!(f, "{key}"),
411            Key::Get(value) => write!(f, "[{:?}]", value.as_reflect()),
412            Key::Variant(variant) => write!(f, "::{variant}"),
413        }
414    }
415}
416
417#[derive(Debug, Clone, Eq, PartialEq, Hash)]
418#[cfg_attr(feature = "speedy", derive(speedy::Readable, speedy::Writable))]
419#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
420pub enum NamedOrNumbered {
421    Named(String),
422    Numbered(usize),
423}
424
425impl fmt::Display for NamedOrNumbered {
426    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
427        match self {
428            NamedOrNumbered::Named(field) => write!(f, ".{field}"),
429            NamedOrNumbered::Numbered(index) => write!(f, ".{index}"),
430        }
431    }
432}
433
434pub trait IntoKeyOrIndex: private::Sealed {
435    fn into_key_or_index(self) -> NamedOrNumbered;
436}
437
438impl IntoKeyOrIndex for &str {
439    fn into_key_or_index(self) -> NamedOrNumbered {
440        NamedOrNumbered::Named(self.to_owned())
441    }
442}
443
444impl IntoKeyOrIndex for &String {
445    fn into_key_or_index(self) -> NamedOrNumbered {
446        NamedOrNumbered::Named(self.to_owned())
447    }
448}
449
450impl IntoKeyOrIndex for String {
451    fn into_key_or_index(self) -> NamedOrNumbered {
452        NamedOrNumbered::Named(self)
453    }
454}
455
456impl IntoKeyOrIndex for usize {
457    fn into_key_or_index(self) -> NamedOrNumbered {
458        NamedOrNumbered::Numbered(self)
459    }
460}
461
462pub fn field(field: impl IntoKeyOrIndex) -> KeyPath {
463    KeyPath::default().field(field)
464}
465
466pub fn get(field: impl Into<Value>) -> KeyPath {
467    KeyPath::default().get(field)
468}
469
470pub fn variant(variant: impl Into<String>) -> KeyPath {
471    KeyPath::default().variant(variant)
472}
473
474/// Convenience macro for creating [`KeyPath`]s.
475///
476/// Expands to calls to [`field`], [`get`], [`variant`], and methods on [`KeyPath`].
477#[macro_export]
478macro_rules! key_path {
479    // base case
480    (
481        @go:
482        $path:expr,
483        [],
484    ) => {
485        $path
486    };
487
488    // recursive case (field)
489    (
490        @go:
491        $path:expr,
492        [ . $field:ident $($tt:tt)*],
493    ) => {
494        $crate::key_path!(
495            @go:
496            $path.field(stringify!($field)),
497            [$($tt)*],
498        )
499    };
500
501    // recursive case (field)
502    (
503        @go:
504        $path:expr,
505        [ . $field:literal $($tt:tt)*],
506    ) => {
507        $crate::key_path!(
508            @go:
509            $path.field($field),
510            [$($tt)*],
511        )
512    };
513
514    // recursive case (field)
515    (
516        @go:
517        $path:expr,
518        [ [$field:expr] $($tt:tt)*],
519    ) => {
520        $crate::key_path!(
521            @go:
522            $path.get($field),
523            [$($tt)*],
524        )
525    };
526
527    // recursive case (variant)
528    (
529        @go:
530        $path:expr,
531        [ :: $variant:ident $($tt:tt)*],
532    ) => {
533        $crate::key_path!(
534            @go:
535            $path.variant(stringify!($variant)),
536            [$($tt)*],
537        )
538    };
539
540    // on invalid syntax
541    (
542        @go:
543        $path:expr,
544        [$($tt:tt)*],
545    ) => {
546        compile_error!(concat!("Unexpected tokens ", stringify!($($tt)*)))
547    };
548
549    // entry point
550    ( $($tt:tt)* ) => {
551        $crate::key_path!(
552            @go:
553            $crate::key_path::KeyPath::default(),
554            [$($tt)*],
555        )
556    };
557}
558
559impl fmt::Display for KeyPath {
560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561        for key in &self.path {
562            write!(f, "{key}")?;
563        }
564        Ok(())
565    }
566}
567
568pub(crate) fn value_to_usize(value: &Value) -> Option<usize> {
569    match value {
570        Value::usize(n) => Some(*n),
571        Value::u8(n) => Some(*n as usize),
572        Value::u16(n) => Some(*n as usize),
573        Value::u32(n) => Some(*n as usize),
574        Value::u64(n) => Some(*n as usize),
575        Value::u128(n) => Some(*n as usize),
576        Value::i8(n) => Some(*n as usize),
577        Value::i16(n) => Some(*n as usize),
578        Value::i32(n) => Some(*n as usize),
579        Value::i64(n) => Some(*n as usize),
580        Value::i128(n) => Some(*n as usize),
581        Value::bool(_)
582        | Value::char(_)
583        | Value::f32(_)
584        | Value::f64(_)
585        | Value::String(_)
586        | Value::StructValue(_)
587        | Value::EnumValue(_)
588        | Value::TupleStructValue(_)
589        | Value::TupleValue(_)
590        | Value::List(_)
591        | Value::Map(_) => None,
592    }
593}
594
595impl FromIterator<Key> for KeyPath {
596    fn from_iter<T>(iter: T) -> Self
597    where
598        T: IntoIterator<Item = Key>,
599    {
600        Self {
601            path: Vec::from_iter(iter),
602        }
603    }
604}
605
606#[derive(Debug)]
607pub struct Breadcrumbs<'a> {
608    key_path: &'a KeyPath,
609    index: usize,
610}
611
612impl<'a> Iterator for Breadcrumbs<'a> {
613    type Item = &'a [Key];
614
615    fn next(&mut self) -> Option<Self::Item> {
616        let keys = self.key_path.path.get(0..self.index)?;
617        self.index += 1;
618        Some(keys)
619    }
620}