Skip to content

Commit 200e44b

Browse files
committed
Add push, join_*, and empty methods to ParsedPath.
1 parent 53ddd5e commit 200e44b

File tree

1 file changed

+108
-0
lines changed
  • crates/bevy_reflect/src/path

1 file changed

+108
-0
lines changed

crates/bevy_reflect/src/path/mod.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
pub mod access;
2+
23
pub use access::*;
4+
use alloc::borrow::Cow;
35

46
mod error;
57
pub use error::*;
@@ -372,6 +374,26 @@ pub struct ParsedPath(
372374
);
373375

374376
impl ParsedPath {
377+
/// Create a new, empty [`ParsedPath`]. This path won't perform any accesses, returning a
378+
/// top-level value unchanged.
379+
///
380+
/// # Example
381+
/// ```
382+
/// # use bevy_reflect::{ParsedPath, Reflect, ReflectPath};
383+
///
384+
/// #[derive(Debug, PartialEq, Reflect)]
385+
/// struct Foo(f64, u32);
386+
///
387+
/// let foo = Foo(0.0, 1);
388+
///
389+
/// let empty_path = ParsedPath::empty();
390+
/// assert_eq!(empty_path.element::<bool>(&true).unwrap(), &true);
391+
/// assert_eq!(empty_path.element::<Foo>(&foo).unwrap(), &foo);
392+
/// ```
393+
pub fn empty() -> Self {
394+
Self(Vec::new())
395+
}
396+
375397
/// Parses a [`ParsedPath`] from a string.
376398
///
377399
/// Returns an error if the string does not represent a valid path to an element.
@@ -439,6 +461,92 @@ impl ParsedPath {
439461
}
440462
Ok(Self(parts))
441463
}
464+
465+
/// Append a field access to the end of the path.
466+
pub fn push_field(&mut self, field: &str) -> &mut Self {
467+
self.0.push(OffsetAccess {
468+
access: Access::Field(Cow::Owned(field.into())),
469+
offset: None,
470+
});
471+
self
472+
}
473+
474+
/// Similar to [`Self::push_field`] but only works on `&'static str`
475+
/// and does not allocate.
476+
pub fn push_field_static(&mut self, field: &'static str) -> &mut Self {
477+
self.0.push(OffsetAccess {
478+
access: Access::Field(Cow::Borrowed(field)),
479+
offset: None,
480+
});
481+
self
482+
}
483+
484+
/// Append a field index access to the end of the path.
485+
pub fn push_field_index(&mut self, idx: usize) -> &mut Self {
486+
self.0.push(OffsetAccess {
487+
access: Access::FieldIndex(idx),
488+
offset: None,
489+
});
490+
self
491+
}
492+
493+
/// Append a list access to the end of the path.
494+
pub fn push_list_index(&mut self, idx: usize) -> &mut Self {
495+
self.0.push(OffsetAccess {
496+
access: Access::ListIndex(idx),
497+
offset: None,
498+
});
499+
self
500+
}
501+
502+
/// Append a tuple index access to the end of the path.
503+
pub fn push_tuple_index(&mut self, idx: usize) -> &mut Self {
504+
self.0.push(OffsetAccess {
505+
access: Access::TupleIndex(idx),
506+
offset: None,
507+
});
508+
self
509+
}
510+
511+
/// Join two paths, chaining their accesses. This will produce a new [`ParsedPath`] that
512+
/// performs the accesses of this path and then the other path in order.
513+
///
514+
/// # Example
515+
/// ```
516+
/// # use bevy_reflect::{ParsedPath, Reflect, ReflectPath};
517+
/// #[derive(Reflect)]
518+
/// struct Foo {
519+
/// bar: Bar,
520+
/// }
521+
///
522+
/// #[derive(Reflect)]
523+
/// struct Bar {
524+
/// baz: Baz,
525+
/// }
526+
///
527+
/// #[derive(Clone, Debug, PartialEq, Reflect)]
528+
/// struct Baz(f32, Vec<Option<u32>>);
529+
///
530+
/// let baz = Baz(3.14, vec![None, None, Some(123)]);
531+
///
532+
/// let foo = Foo {
533+
/// bar: Bar {
534+
/// baz: baz.clone(),
535+
/// },
536+
/// };
537+
///
538+
/// let first_path = ParsedPath::parse(".bar#0").unwrap();
539+
/// let second_path = ParsedPath::parse(".1[2].0").unwrap();
540+
///
541+
/// let joined_path = first_path.join(&second_path);
542+
///
543+
/// assert_eq!(first_path.element::<Baz>(&foo).unwrap(), &baz);
544+
/// assert_eq!(second_path.element::<u32>(&baz).unwrap(), &123);
545+
/// assert_eq!(joined_path.element::<u32>(&foo).unwrap(), &123);
546+
/// ```
547+
pub fn join(&self, other: &Self) -> ParsedPath {
548+
ParsedPath(self.0.iter().chain(other.0.iter()).cloned().collect())
549+
}
442550
}
443551

444552
impl<'a> ReflectPath<'a> for &'a ParsedPath {

0 commit comments

Comments
 (0)