Don't panic in AssetPath deserialization (#23935)

## Objective

`AssetPath` deserialization panics if the path is malformed. This seems
a bit rude, and prevents the user from getting deserialization errors
that would help track down the problem.

## Solution

Instead of calling `AssetPath::parse`, call `AssetPath::try_parse` and
handle any errors.

Now, calling `ron::de::from_str` on `"a/b.test#"` returns a useful
error:

```rust
Err(SpannedError {
    code: Message(
        "Asset label must be at least one character. Either specify the label after the '#' or remove the '#'",
    ),
    span: Span {
        start: Position { line: 1, col: 2, },
        end: Position { line: 1, col: 12 },
    },
})
```

The PR also removes the `visit_string` method of the `AssetPath`
deserializer. `visit_string` is an optimization that avoids copies when
the deserializer can take ownership of the string (see [serde
docs](https://docs.rs/serde/latest/serde/de/trait.Visitor.html#method.visit_string)).
But `AssetPath` didn't take ownership of the string, so there's no
reason to implement it.

## Testing

```sh
cargo test -p bevy_asset
cargo run --example world_serialization
```
This commit is contained in:
Greeble
2026-04-22 19:12:45 +01:00
committed by GitHub
parent 4dc8fb4919
commit f794d8ac8a
+10 -8
View File
@@ -680,14 +680,10 @@ impl<'de> Visitor<'de> for AssetPathVisitor {
where
E: serde::de::Error,
{
Ok(AssetPath::parse(v).into_owned())
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(AssetPath::from(v))
match AssetPath::try_parse(v) {
Ok(path) => Ok(path.into_owned()),
Err(err) => Err(E::custom(err)),
}
}
}
@@ -772,6 +768,12 @@ mod tests {
assert_eq!(result, Err(crate::ParseAssetPathError::MissingLabel));
}
#[test]
fn test_serialize() {
assert!(ron::de::from_str::<AssetPath>("\"a/b.test\"").is_ok());
assert!(ron::de::from_str::<AssetPath>("\"a/b.test#\"").is_err());
}
#[test]
fn test_parent() {
// Parent consumes path segments, returns None when insufficient