scuffle_cedar_policy/
entity_type_name.rs1const 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#[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 pub const fn as_str(&self) -> &'static str {
62 self.0
63 }
64}
65
66#[macro_export]
71macro_rules! entity_type_name {
72 ($text:expr) => {
73 const { $crate::EntityTypeName::new($text) }
74 };
75}