|
1 | 1 | pub mod access; |
| 2 | + |
2 | 3 | pub use access::*; |
| 4 | +use alloc::borrow::Cow; |
3 | 5 |
|
4 | 6 | mod error; |
5 | 7 | pub use error::*; |
@@ -372,6 +374,26 @@ pub struct ParsedPath( |
372 | 374 | ); |
373 | 375 |
|
374 | 376 | 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 | + |
375 | 397 | /// Parses a [`ParsedPath`] from a string. |
376 | 398 | /// |
377 | 399 | /// Returns an error if the string does not represent a valid path to an element. |
@@ -439,6 +461,92 @@ impl ParsedPath { |
439 | 461 | } |
440 | 462 | Ok(Self(parts)) |
441 | 463 | } |
| 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 | + } |
442 | 550 | } |
443 | 551 |
|
444 | 552 | impl<'a> ReflectPath<'a> for &'a ParsedPath { |
|
0 commit comments