Expand description
Streaming-path registry for custom YAML tag pass-through.
The default streaming deserializer routes values carrying a non-core
tag (anything outside !!int, !!str, !!bool, …) through the AST
fallback so the tag survives as Value::Tagged(...). That’s correct
when a caller is reading into Value, but it forces an unnecessary
allocation when the caller already knows the tag maps to a concrete
Rust type.
TagRegistry lets a caller declare which custom tags should
instead be stripped on the streaming path so the inner scalar,
sequence, or mapping deserializes directly into the target type —
no AST detour, no #[serde(rename = "!…")] dance.
§Examples
use noyalib::{from_str_with_config, ParserConfig, TagRegistry};
use std::sync::Arc;
#[derive(Debug, serde::Deserialize, PartialEq)]
struct Celsius(f64);
let registry = Arc::new(TagRegistry::new().with("!Celsius"));
let cfg = ParserConfig::new().tag_registry(registry);
// Without the registry, `!Celsius 42.5` becomes Value::Tagged and a
// plain `f64` deserialize fails. With the registry, the tag is
// stripped on the streaming path and the scalar deserializes
// directly into the target type.
let c: Celsius = from_str_with_config("!Celsius 42.5", &cfg).unwrap();
assert_eq!(c, Celsius(42.5));§When you still need #[serde(rename = "!tag")]
The registry strips tags; it does not dispatch. If you’re reading a
tagged value into an enum where the tag chooses the variant
(!bang → Msg::Bang, !quiet → Msg::Quiet), keep using
#[serde(rename)] — serde itself needs the tag string to pick the
variant. The registry is for “I already know the type; just get out
of my way” newtype/unit-style use cases (the robotics, scientific,
and units scenarios in particular).
Structs§
- TagRegistry
- A set of custom YAML tags that the streaming deserializer should strip and pass through instead of routing via the AST fallback.