scuffle_cedar_policy/
entity_type_name.rs

1// ^[_a-zA-Z][_a-zA-Z0-9]*(?:::[_a-zA-Z][_a-zA-Z0-9]*)*$
2
3const fn validate_part(part: &str) {
4    let invalid_parts = &["true", "false", "if", "then", "else", "in", "is", "like", "has", "__cedar"];
5    konst::for_range! {idx in 0..invalid_parts.len() =>
6        if konst::string::eq_str(invalid_parts[idx], part) {
7            const_panic::concat_panic!("part cannot be a reserved keyword: ", part);
8        }
9    }
10}
11
12const fn validate(input: &str) {
13    konst::iter::for_each! {part in konst::string::split(input, "::") =>
14        validate_part(part);
15
16        let mut chars = konst::string::chars(part);
17
18        let Some(c) = chars.next() else {
19            panic!("part must be non empty");
20        };
21
22        if c != '_' && !c.is_ascii_alphabetic() {
23            const_panic::concat_panic!("part must start with either a '_' or any alphabetic character but started with: ", c);
24        }
25
26        konst::iter::for_each!{c in chars =>
27            if c != '_' && !c.is_ascii_alphanumeric() {
28                const_panic::concat_panic!("part can only contain '_' or alphanumeric characters but contained: ", c);
29            }
30        }
31    }
32}
33
34/// A compile time checked entity type name
35#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
36pub struct EntityTypeName(&'static str);
37
38impl serde::Serialize for EntityTypeName {
39    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
40    where
41        S: serde::Serializer,
42    {
43        serializer.serialize_str(self.0)
44    }
45}
46
47impl std::fmt::Display for EntityTypeName {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        self.0.fmt(f)
50    }
51}
52
53impl EntityTypeName {
54    #[doc(hidden)]
55    pub const fn new(input: &'static str) -> Self {
56        validate(input);
57        EntityTypeName(input)
58    }
59
60    /// Get the string value out of the entity type name.
61    pub const fn as_str(&self) -> &'static str {
62        self.0
63    }
64}
65
66/// A macro for creating a compile time checked entity type name
67/// ```rust
68/// scuffle_cedar_policy::entity_type_name!("SomeEntityType");
69/// ```
70#[macro_export]
71macro_rules! entity_type_name {
72    ($text:expr) => {
73        const { $crate::EntityTypeName::new($text) }
74    };
75}