|
> What about user-supplied JSON schemas? You can't add types at runtime. Right, well, since they're validators anyway, might as well represent them as a defunctionalized validation function or something.
Agreed that this is more-or-less past the point where the type system helps model the values you're validating, though a strong type system helps a lot implementing the validators! > It's still a string, in Rust you would need an enum and a deserializer from the string to the enum. Yep, though if you really wanted it to be a string at runtime, you could use smart constructors to make it so. The downsides would be, unless you normalized the string (at which point, just use an enum TBH), you're doing O(n) comparison, and you're keeping memory alive, whether by owning it, leaking it, reference counting, [...]. Thankfully due to Rust's #[derive] feature, the programmer wouldn't need to write the serializer/deserializer though; crates like strum can generate it for you, such that you can simply write: use strum::{AsRefStr, EnumString};
#[derive(AsRefStr, EnumString, PartialEq)]
enum Role {
Admin,
Moderator,
Member,
Anonymous,
}
fn main() {
assert_eq!(Role::from_str("Admin").unwrap(), Role::Admin);
assert_eq!(Role::Member.as_ref(), "Member");
}
(strum also has also a derive for the standard library Display trait, which provides a .to_string() method, but this has the disadvantage of heap allocating; EnumString (which provides .as_ref()) compiles in the strings, so no allocation is needed, and .as_ref() is a simple table lookup.)[0]: https://docs.rs/strum/0.20.0/strum/index.html |
Nit: it's more constraining but serde can deserialize to an &str, though that assumes the value has no escapes.
Ideally `Cow<str>` would be the solution, but while it kind-of is, that doesn't actually work out of the box: https://github.com/serde-rs/serde/issues/1852