miden_protocol/account/
access.rs1use alloc::fmt;
2
3use crate::Felt;
4use crate::errors::RoleSymbolError;
5use crate::utils::ShortCapitalString;
6
7#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
15pub struct RoleSymbol(ShortCapitalString);
16
17impl RoleSymbol {
18 pub const ALPHABET: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
20
21 pub const MIN_ENCODED_VALUE: u64 = 1;
25
26 pub const MAX_ENCODED_VALUE: u64 = 4052555153018976252;
30
31 pub fn new_unchecked(role_symbol: &str) -> Self {
39 Self::new(role_symbol).expect("invalid role symbol")
40 }
41
42 pub fn new(role_symbol: &str) -> Result<Self, RoleSymbolError> {
49 ShortCapitalString::from_ascii_uppercase_and_underscore(role_symbol)
50 .map(Self)
51 .map_err(Into::into)
52 }
53
54 pub fn as_element(&self) -> Felt {
56 self.0.as_element(Self::ALPHABET).expect("RoleSymbol alphabet is always valid")
57 }
58}
59
60impl fmt::Display for RoleSymbol {
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 self.0.fmt(f)
63 }
64}
65
66impl From<RoleSymbol> for Felt {
67 fn from(role_symbol: RoleSymbol) -> Self {
68 role_symbol.as_element()
69 }
70}
71
72impl From<&RoleSymbol> for Felt {
73 fn from(role_symbol: &RoleSymbol) -> Self {
74 role_symbol.as_element()
75 }
76}
77
78impl TryFrom<&str> for RoleSymbol {
79 type Error = RoleSymbolError;
80
81 fn try_from(role_symbol: &str) -> Result<Self, Self::Error> {
82 Self::new(role_symbol)
83 }
84}
85
86impl TryFrom<Felt> for RoleSymbol {
87 type Error = RoleSymbolError;
88
89 fn try_from(felt: Felt) -> Result<Self, Self::Error> {
91 ShortCapitalString::try_from_encoded_felt(
92 felt,
93 Self::ALPHABET,
94 Self::MIN_ENCODED_VALUE,
95 Self::MAX_ENCODED_VALUE,
96 )
97 .map(Self)
98 .map_err(Into::into)
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use alloc::string::ToString;
105
106 use assert_matches::assert_matches;
107
108 use super::{Felt, RoleSymbol};
109 use crate::errors::RoleSymbolError;
110
111 #[test]
112 fn test_role_symbol_roundtrip_and_validation() {
113 let role_symbols = ["MINTER", "BURNER", "MINTER_ADMIN", "A", "A_B_C"];
114 for role_symbol in role_symbols {
115 let encoded: Felt = RoleSymbol::new(role_symbol).unwrap().into();
116 let decoded = RoleSymbol::try_from(encoded).unwrap();
117 assert_eq!(decoded.to_string(), role_symbol);
118 }
119
120 assert_matches!(RoleSymbol::new("").unwrap_err(), RoleSymbolError::InvalidLength(0));
121 assert_matches!(
122 RoleSymbol::new("ABCDEFGHIJKLM").unwrap_err(),
123 RoleSymbolError::InvalidLength(13)
124 );
125 assert_matches!(
126 RoleSymbol::new("MINTER-ADMIN").unwrap_err(),
127 RoleSymbolError::InvalidCharacter
128 );
129 assert_matches!(RoleSymbol::new("mINTER").unwrap_err(), RoleSymbolError::InvalidCharacter);
130 }
131}