cedar_policy_core/from_normalized_str.rs
1use crate::parser::err::ParseError;
2use std::fmt::Display;
3use std::str::FromStr;
4
5/// Trait for parsing "normalized" strings only, throwing an error if a
6/// non-normalized string is encountered. See docs on the
7/// [`from_normalized_str`] trait function.
8pub trait FromNormalizedStr: FromStr<Err = Vec<ParseError>> + Display {
9 /// Create a `Self` by parsing a string, which is required to be normalized.
10 /// That is, the input is required to roundtrip with the `Display` impl on `Self`:
11 /// `Self::from_normalized_str(x).to_string() == x` must hold.
12 ///
13 /// In Cedar's context, that means that `from_normalized_str()` will not
14 /// accept strings with spurious whitespace (e.g. `A :: B :: C::"foo"`),
15 /// Cedar comments (e.g. `A::B::"bar" // comment`), etc. See
16 /// [RFC 9](https://github.com/cedar-policy/rfcs/blob/main/text/0009-disallow-whitespace-in-entityuid.md)
17 /// for more details and justification.
18 ///
19 /// For the version that accepts whitespace and Cedar comments, use the
20 /// actual `FromStr` implementations.
21 fn from_normalized_str(s: &str) -> Result<Self, Vec<ParseError>> {
22 let parsed = Self::from_str(s)?;
23 let normalized = parsed.to_string();
24 if normalized == s {
25 // the normalized representation is indeed the one that was provided
26 Ok(parsed)
27 } else {
28 Err(vec![ParseError::ToAST(format!(
29 "{} needs to be normalized (e.g., whitespace removed): {s} The normalized form is {normalized}",
30 Self::describe_self()
31 ))])
32 }
33 }
34
35 /// Short string description of the `Self` type, to be used in error messages.
36 /// What are we trying to parse?
37 fn describe_self() -> &'static str;
38}