1use super::*;
2
3impl RoleParam {
5 pub fn validate(&self) -> RoleValidationResult<()> {
7 match self {
8 RoleParam::Static(count) => {
9 if *count > MAX_ROLE_COUNT {
10 return Err(RoleValidationError::CountOverflow {
11 count: *count,
12 max: MAX_ROLE_COUNT,
13 });
14 }
15 Ok(())
16 }
17 RoleParam::Symbolic(_) => Ok(()),
18 RoleParam::Runtime => Ok(()),
19 }
20 }
21
22 pub fn validate_with_index(&self, index: &RoleIndex) -> RoleValidationResult<()> {
24 match (self, index) {
25 (RoleParam::Static(count), RoleIndex::Concrete(idx)) => {
26 if *idx >= *count {
27 return Err(RoleValidationError::IndexOverflow {
28 index: *idx,
29 max: *count - 1,
30 });
31 }
32 Ok(())
33 }
34 (RoleParam::Static(count), RoleIndex::Range(range)) => {
35 if let (RangeExpr::Concrete(_), RangeExpr::Concrete(end)) =
36 (&range.start, &range.end)
37 {
38 if *end > *count {
39 return Err(RoleValidationError::IndexOverflow {
40 index: *end,
41 max: *count,
42 });
43 }
44 }
45 Ok(())
46 }
47 _ => Ok(()),
48 }
49 }
50
51 pub fn safe_static(count: u32) -> RoleValidationResult<Self> {
53 if count > MAX_ROLE_COUNT {
54 return Err(RoleValidationError::CountOverflow {
55 count,
56 max: MAX_ROLE_COUNT,
57 });
58 }
59 Ok(RoleParam::Static(count))
60 }
61}
62
63impl RoleIndex {
64 pub fn validate(&self) -> RoleValidationResult<()> {
66 match self {
67 RoleIndex::Concrete(index) => {
68 if *index > MAX_ROLE_INDEX {
69 return Err(RoleValidationError::IndexOverflow {
70 index: *index,
71 max: MAX_ROLE_INDEX,
72 });
73 }
74 Ok(())
75 }
76 RoleIndex::Symbolic(_) | RoleIndex::Wildcard => Ok(()),
77 RoleIndex::Range(range) => range.validate(),
78 }
79 }
80
81 pub fn safe_concrete(index: u32) -> RoleValidationResult<Self> {
83 if index > MAX_ROLE_INDEX {
84 return Err(RoleValidationError::IndexOverflow {
85 index,
86 max: MAX_ROLE_INDEX,
87 });
88 }
89 Ok(RoleIndex::Concrete(index))
90 }
91}
92
93impl RoleRange {
94 pub fn validate(&self) -> RoleValidationResult<()> {
96 self.start.validate()?;
97 self.end.validate()?;
98
99 if let (RangeExpr::Concrete(start), RangeExpr::Concrete(end)) = (&self.start, &self.end) {
100 if start >= end {
101 return Err(RoleValidationError::InvalidRange {
102 start: *start,
103 end: *end,
104 });
105 }
106
107 let range_size = end - start;
108 if range_size > MAX_RANGE_COUNT {
109 return Err(RoleValidationError::RangeSizeOverflow {
110 size: range_size,
111 max: MAX_RANGE_COUNT,
112 });
113 }
114 }
115
116 Ok(())
117 }
118
119 pub fn safe_concrete(start: u32, end: u32) -> RoleValidationResult<Self> {
121 let range = RoleRange {
122 start: RangeExpr::Concrete(start),
123 end: RangeExpr::Concrete(end),
124 };
125 range.validate()?;
126 Ok(range)
127 }
128}
129
130impl RangeExpr {
131 pub fn validate(&self) -> RoleValidationResult<()> {
133 match self {
134 RangeExpr::Concrete(value) => {
135 if *value > MAX_ROLE_INDEX {
136 return Err(RoleValidationError::IndexOverflow {
137 index: *value,
138 max: MAX_ROLE_INDEX,
139 });
140 }
141 Ok(())
142 }
143 RangeExpr::Symbolic(_) => Ok(()),
144 }
145 }
146}
147
148pub struct RoleBoundsChecker {
150 max_count: u32,
151 max_index: u32,
152}
153
154impl Default for RoleBoundsChecker {
155 fn default() -> Self {
156 Self {
157 max_count: MAX_ROLE_COUNT,
158 max_index: MAX_ROLE_INDEX,
159 }
160 }
161}
162
163impl RoleBoundsChecker {
164 pub fn new(max_count: u32, max_index: u32) -> Self {
166 Self {
167 max_count,
168 max_index,
169 }
170 }
171
172 pub fn check_count(&self, count: u32) -> RoleValidationResult<()> {
174 if count > self.max_count {
175 return Err(RoleValidationError::CountOverflow {
176 count,
177 max: self.max_count,
178 });
179 }
180 Ok(())
181 }
182
183 pub fn check_index(&self, index: u32) -> RoleValidationResult<()> {
185 if index > self.max_index {
186 return Err(RoleValidationError::IndexOverflow {
187 index,
188 max: self.max_index,
189 });
190 }
191 Ok(())
192 }
193
194 pub fn check_range(&self, start: u32, end: u32) -> RoleValidationResult<()> {
196 if start >= end {
197 return Err(RoleValidationError::InvalidRange { start, end });
198 }
199
200 if end > self.max_index {
201 return Err(RoleValidationError::IndexOverflow {
202 index: end,
203 max: self.max_index,
204 });
205 }
206
207 let range_size = end - start;
208 if range_size > MAX_RANGE_COUNT {
209 return Err(RoleValidationError::RangeSizeOverflow {
210 size: range_size,
211 max: MAX_RANGE_COUNT,
212 });
213 }
214
215 Ok(())
216 }
217}
218
219impl std::fmt::Display for RoleIndex {
220 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
221 match self {
222 RoleIndex::Concrete(index) => write!(f, "{}", index),
223 RoleIndex::Symbolic(name) => write!(f, "{}", name),
224 RoleIndex::Wildcard => write!(f, "*"),
225 RoleIndex::Range(range) => write!(f, "{}", range),
226 }
227 }
228}
229
230impl std::fmt::Display for RoleRange {
231 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
232 write!(f, "{}..{}", self.start, self.end)
233 }
234}
235
236impl std::fmt::Display for RangeExpr {
237 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
238 match self {
239 RangeExpr::Concrete(value) => write!(f, "{}", value),
240 RangeExpr::Symbolic(name) => write!(f, "{}", name),
241 }
242 }
243}
244
245impl std::fmt::Display for RoleParam {
246 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247 match self {
248 RoleParam::Static(count) => write!(f, "{}", count),
249 RoleParam::Symbolic(name) => write!(f, "{}", name),
250 RoleParam::Runtime => write!(f, "*"),
251 }
252 }
253}