Skip to content

Commit

Permalink
bevy_reflect: Pre-parsed paths (#7321)
Browse files Browse the repository at this point in the history
# Objective

> ℹ️ **This is an adoption of #4081 by @james7132**

Fixes #4080.

Provide a way to pre-parse reflection paths so as to avoid having to parse at each call to `GetPath::path` (or similar method).

## Solution

Adds the `ParsedPath` struct (named `FieldPath` in the original PR) that parses and caches the sequence of accesses to a reflected element. This is functionally similar to the `GetPath` trait, but removes the need to parse an unchanged path more than once.

### Additional Changes

Included in this PR from the original is cleaner code as well as the introduction of a new pathing operation: field access by index. This allows struct and struct variant fields to be accessed in a more performant (albeit more fragile) way if needed. This operation is faster due to not having to perform string matching. As an example, if we wanted the third field on a struct, we'd write `#2`—where `#` denotes indexed access and `2` denotes the desired field index.

This PR also contains improved documentation for `GetPath` and friends, including renaming some of the methods to be more clear to the end-user with a reduced risk of getting them mixed up.

### Future Work

There are a few things that could be done as a separate PR (order doesn't matter— they could be followup PRs or done in parallel). These are:

- [x] ~~Add support for `Tuple`. Currently, we hint that they work but they do not.~~ See #7324
- [ ] Cleanup `ReflectPathError`. I think it would be nicer to give `ReflectPathError` two variants: `ReflectPathError::ParseError` and `ReflectPathError::AccessError`, with all current variants placed within one of those two. It's not obvious when one might expect to receive one type of error over the other, so we can help by explicitly categorizing them.

---

## Changelog

- Cleaned up `GetPath` logic
- Added `ParsedPath` for cached reflection paths
- Added new reflection path syntax: struct field access by index (example syntax: `foo#1`)
- Renamed methods on `GetPath`:
  - `path` -> `reflect_path`
  - `path_mut` -> `reflect_path_mut`
  - `get_path` -> `path`
  - `get_path_mut` -> `path_mut`

## Migration Guide

`GetPath` methods have been renamed according to the following:
- `path` -> `reflect_path`
- `path_mut` -> `reflect_path_mut`
- `get_path` -> `path`
- `get_path_mut` -> `path_mut`


Co-authored-by: Gino Valente <[email protected]>
  • Loading branch information
james7132 and MrGVSV committed Jan 22, 2023
1 parent 7ebc68b commit 8cd59b6
Show file tree
Hide file tree
Showing 2 changed files with 837 additions and 337 deletions.
10 changes: 8 additions & 2 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1274,9 +1274,15 @@ bevy_reflect::tests::should_reflect_debug::Test {
fn vec3_path_access() {
let mut v = vec3(1.0, 2.0, 3.0);

assert_eq!(*v.path("x").unwrap().downcast_ref::<f32>().unwrap(), 1.0);
assert_eq!(
*v.reflect_path("x").unwrap().downcast_ref::<f32>().unwrap(),
1.0
);

*v.path_mut("y").unwrap().downcast_mut::<f32>().unwrap() = 6.0;
*v.reflect_path_mut("y")
.unwrap()
.downcast_mut::<f32>()
.unwrap() = 6.0;

assert_eq!(v.y, 6.0);
}
Expand Down
Loading

0 comments on commit 8cd59b6

Please sign in to comment.