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 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 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 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 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 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 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 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 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 pub fn named_field(name: impl Into<String>) -> Self {
388 Self::Field(NamedOrNumbered::Named(name.into()))
389 }
390
391 pub fn numbered_field(index: usize) -> Self {
393 Self::Field(NamedOrNumbered::Numbered(index))
394 }
395
396 pub fn get(value: impl Into<Value>) -> Self {
398 Self::Get(value.into())
399 }
400
401 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#[macro_export]
478macro_rules! key_path {
479 (
481 @go:
482 $path:expr,
483 [],
484 ) => {
485 $path
486 };
487
488 (
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 (
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 (
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 (
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 (
542 @go:
543 $path:expr,
544 [$($tt:tt)*],
545 ) => {
546 compile_error!(concat!("Unexpected tokens ", stringify!($($tt)*)))
547 };
548
549 ( $($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}