1use std::{
2 borrow::Cow,
3 collections::HashMap,
4 convert::TryFrom,
5 fmt::{Display, Formatter, Write},
6 hash::Hash,
7};
8
9use serde::{Deserialize, Serialize};
10
11use super::{Action, ActionName};
12
13#[derive(Clone, Debug, Serialize, Deserialize)]
16#[must_use]
17pub struct Statement {
18 pub resources: Vec<ResourceName<'static>>,
20 pub actions: Option<ActionNameList>,
22 pub configuration: Option<HashMap<String, Configuration>>,
24}
25
26impl Statement {
27 pub fn allow_all_for_any_resource() -> Self {
30 Self::for_any().allowing_all()
31 }
32
33 pub fn for_resource(name: impl Into<ResourceName<'static>>) -> Self {
35 Self {
36 resources: vec![name.into()],
37 actions: None,
38 configuration: None,
39 }
40 }
41
42 pub fn for_any() -> Self {
44 Self {
45 resources: vec![ResourceName::any()],
46 actions: None,
47 configuration: None,
48 }
49 }
50
51 pub fn for_resources<II: IntoIterator<Item = ResourceName<'static>>>(names: II) -> Self {
53 Self {
54 resources: names.into_iter().collect(),
55 actions: None,
56 configuration: None,
57 }
58 }
59
60 pub fn allow<A: Action>(&mut self, action: &A) {
62 match &mut self.actions {
63 Some(ActionNameList::All) => {}
64 Some(ActionNameList::List(names)) => {
65 names.push(action.name());
66 }
67 None => {
68 self.actions = Some(ActionNameList::List(vec![action.name()]));
69 }
70 }
71 }
72
73 pub fn allowing<A: Action>(mut self, action: &A) -> Self {
75 self.allow(action);
76 self
77 }
78
79 pub fn allow_all(&mut self) {
81 self.actions = Some(ActionNameList::All);
82 }
83
84 pub fn allowing_all(mut self) -> Self {
86 self.allow_all();
87 self
88 }
89
90 pub fn configure<S: Into<String>, C: Into<Configuration>>(&mut self, key: S, configuration: C) {
92 let configurations = self.configuration.get_or_insert_with(HashMap::default);
93 configurations.insert(key.into(), configuration.into());
94 }
95
96 pub fn with<S: Into<String>, C: Into<Configuration>>(
98 mut self,
99 key: S,
100 configuration: C,
101 ) -> Self {
102 self.configure(key, configuration);
103 self
104 }
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub enum Identifier<'a> {
110 Any,
113 Integer(u64),
115 String(Cow<'a, str>),
117 Bytes(Cow<'a, [u8]>),
119}
120
121impl<'a> Hash for Identifier<'a> {
122 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
123 match self {
126 Identifier::Any => {
127 state.write_u8(0);
131 }
132 Identifier::Integer(int) => {
133 state.write(&int.to_be_bytes());
134 }
135 Identifier::String(string) => {
136 state.write(string.as_bytes());
137 }
138 Identifier::Bytes(bytes) => {
139 state.write(bytes);
140 }
141 }
142 }
143}
144
145#[test]
146fn identifier_hash_tests() {
147 fn hash(identifier: &Identifier<'_>) -> u64 {
148 use std::hash::Hasher;
149 let mut hasher = std::collections::hash_map::DefaultHasher::default();
150 identifier.hash(&mut hasher);
151 hasher.finish()
152 }
153
154 let integer_a = Identifier::from(u64::from_be_bytes(*b"helloooo"));
155 let string_a = Identifier::from("helloooo");
156 let bytes_a = Identifier::from(b"helloooo");
157 let string_b = Identifier::from("woooorld");
158
159 assert_eq!(hash(&Identifier::Any), hash(&Identifier::Any));
160 assert_eq!(hash(&string_a), hash(&string_a));
161 assert_eq!(hash(&integer_a), hash(&string_a));
162 assert_eq!(hash(&bytes_a), hash(&string_a));
163 assert_ne!(hash(&string_a), hash(&string_b));
164 assert_ne!(hash(&integer_a), hash(&string_b));
165 assert_ne!(hash(&bytes_a), hash(&string_b));
166}
167
168impl<'a> Eq for Identifier<'a> {}
169
170impl<'a> PartialEq for Identifier<'a> {
171 fn eq(&self, other: &Self) -> bool {
172 match other {
173 Self::Any => matches!(self, Self::Any),
174 Self::Integer(int) => self.eq_int(*int),
175 Self::String(string) => self.eq_str(string),
176 Self::Bytes(bytes) => self.eq_bytes(bytes),
177 }
178 }
179}
180
181impl<'a> Identifier<'a> {
182 #[must_use]
184 pub fn to_owned(&self) -> Identifier<'static> {
185 match self {
186 Self::Any => Identifier::Any,
187 Self::Integer(value) => Identifier::Integer(*value),
188 Self::String(value) => Identifier::String(Cow::Owned(value.to_string())),
189 Self::Bytes(value) => Identifier::Bytes(Cow::Owned(value.to_vec())),
190 }
191 }
192
193 fn eq_int(&self, other: u64) -> bool {
194 match self {
195 Identifier::Any => false,
196 Identifier::Integer(int) => *int == other,
197 Identifier::String(string) => {
198 let other = other.to_be_bytes();
199 string.as_bytes() == other
200 }
201 Identifier::Bytes(bytes) => {
202 let other = other.to_be_bytes();
203 **bytes == other
204 }
205 }
206 }
207
208 fn eq_str(&self, other: &str) -> bool {
209 match self {
210 Identifier::Any => false,
211 Identifier::Integer(int) => {
212 let int = int.to_be_bytes();
213 int == other.as_bytes()
214 }
215 Identifier::String(string) => string == other,
216 Identifier::Bytes(bytes) => &**bytes == other.as_bytes(),
217 }
218 }
219
220 fn eq_bytes(&self, other: &[u8]) -> bool {
221 match self {
222 Identifier::Any => false,
223 Identifier::Integer(int) => {
224 let int = int.to_be_bytes();
225 int == other
226 }
227 Identifier::String(string) => string.as_bytes() == other,
228 Identifier::Bytes(bytes) => &**bytes == other,
229 }
230 }
231}
232
233#[test]
234fn identifier_equality_tests() {
235 let integer_a = Identifier::from(u64::from_be_bytes(*b"helloooo"));
236 let integer_b = Identifier::from(u64::from_be_bytes(*b"woooorld"));
237 let string_a = Identifier::from("helloooo");
238 let string_b = Identifier::from("woooorld");
239 let bytes_a = Identifier::from(b"helloooo");
240 let bytes_b = Identifier::from(b"woooorld");
241
242 assert_ne!(integer_a, Identifier::Any);
244 assert_eq!(integer_a, integer_a);
245 assert_eq!(integer_a, string_a);
246 assert_eq!(integer_a, bytes_a);
247 assert_ne!(integer_a, integer_b);
248 assert_ne!(integer_a, string_b);
249 assert_ne!(integer_a, bytes_b);
250
251 assert_ne!(string_a, Identifier::Any);
253 assert_eq!(string_a, integer_a);
254 assert_eq!(string_a, string_a);
255 assert_eq!(string_a, bytes_a);
256 assert_ne!(string_a, integer_b);
257 assert_ne!(string_a, string_b);
258 assert_ne!(string_a, bytes_b);
259
260 assert_ne!(bytes_a, Identifier::Any);
262 assert_eq!(bytes_a, integer_a);
263 assert_eq!(bytes_a, string_a);
264 assert_eq!(bytes_a, bytes_a);
265 assert_ne!(bytes_a, integer_b);
266 assert_ne!(bytes_a, string_b);
267 assert_ne!(bytes_a, bytes_b);
268
269 assert_eq!(Identifier::Any, Identifier::Any);
271 assert_ne!(Identifier::Any, integer_a);
272 assert_ne!(Identifier::Any, string_a);
273 assert_ne!(Identifier::Any, bytes_a);
274}
275
276impl<'a> Display for Identifier<'a> {
277 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278 match self {
279 Self::Any => f.write_char('*'),
280 Self::Integer(integer) => integer.fmt(f),
281 Self::String(string) => string.fmt(f),
282 Self::Bytes(bytes) => {
283 f.write_char('$')?;
284 for byte in bytes.iter() {
285 write!(f, "{:02x}", byte)?;
286 }
287 Ok(())
288 }
289 }
290 }
291}
292
293#[test]
294fn identifier_display_tests() {
295 assert_eq!(Identifier::Any.to_string(), "*");
296 assert_eq!(Identifier::from(1).to_string(), "1");
297 assert_eq!(Identifier::from("string").to_string(), "string");
298 assert_eq!(Identifier::from(b"bytes").to_string(), "$6279746573");
299}
300
301impl<'a> From<u64> for Identifier<'a> {
302 fn from(id: u64) -> Self {
303 Self::Integer(id)
304 }
305}
306
307impl<'a> From<&'a str> for Identifier<'a> {
308 fn from(id: &'a str) -> Self {
309 Self::String(Cow::Borrowed(id))
310 }
311}
312
313impl<'a> From<&'a String> for Identifier<'a> {
314 fn from(id: &'a String) -> Self {
315 Self::from(id.as_str())
316 }
317}
318
319impl<'a> From<String> for Identifier<'a> {
320 fn from(id: String) -> Self {
321 Self::String(Cow::Owned(id))
322 }
323}
324
325impl<'a, const N: usize> From<&'a [u8; N]> for Identifier<'a> {
326 fn from(id: &'a [u8; N]) -> Self {
327 Self::from(&id[..])
328 }
329}
330
331impl<'a, const N: usize> From<[u8; N]> for Identifier<'a> {
332 fn from(id: [u8; N]) -> Self {
333 Self::from(id.to_vec())
334 }
335}
336
337impl<'a> From<&'a [u8]> for Identifier<'a> {
338 fn from(id: &'a [u8]) -> Self {
339 Self::Bytes(Cow::Borrowed(id))
340 }
341}
342
343impl<'a> From<&'a Vec<u8>> for Identifier<'a> {
344 fn from(id: &'a Vec<u8>) -> Self {
345 Self::from(id.clone())
346 }
347}
348
349impl<'a> From<Vec<u8>> for Identifier<'a> {
350 fn from(id: Vec<u8>) -> Self {
351 Self::Bytes(Cow::Owned(id))
352 }
353}
354
355#[test]
356fn identifier_from_tests() {
357 assert_eq!(Identifier::from(1).to_string(), "1");
358 assert_eq!(Identifier::from("string").to_string(), "string");
359 assert_eq!(
360 Identifier::from(&String::from("string")).to_string(),
361 "string"
362 );
363 assert_eq!(
364 Identifier::from(String::from("string")).to_string(),
365 "string"
366 );
367 assert_eq!(Identifier::from(b"bytes").to_string(), "$6279746573");
369 assert_eq!(Identifier::from(*b"bytes").to_string(), "$6279746573");
371 assert_eq!(
372 Identifier::from(&b"bytes".to_vec()).to_string(),
373 "$6279746573"
374 );
375}
376
377#[derive(Clone, Debug, Serialize, Deserialize)]
379pub enum ActionNameList {
380 List(Vec<ActionName>),
382 All,
384}
385
386impl<T> From<T> for ActionNameList
387where
388 T: Action,
389{
390 fn from(action: T) -> Self {
391 Self::List(vec![action.name()])
392 }
393}
394
395impl<T> From<Vec<T>> for ActionNameList
396where
397 T: Action,
398{
399 fn from(actions: Vec<T>) -> Self {
400 Self::List(actions.into_iter().map(|action| action.name()).collect())
401 }
402}
403
404#[derive(Debug, Clone, Serialize, Deserialize)]
406pub enum Configuration {
407 Unsigned(u64),
409 Signed(i64),
411 String(String),
413}
414
415impl Configuration {
416 #[must_use]
419 pub fn to_signed(&self) -> Option<i64> {
420 match self {
421 Configuration::Unsigned(unsigned) => i64::try_from(*unsigned).ok(),
422 Configuration::Signed(signed) => Some(*signed),
423 Configuration::String(string) => string.parse().ok(),
424 }
425 }
426
427 #[must_use]
430 pub fn to_unsigned(&self) -> Option<u64> {
431 match self {
432 Configuration::Unsigned(unsigned) => Some(*unsigned),
433 Configuration::Signed(signed) => u64::try_from(*signed).ok(),
434 Configuration::String(string) => string.parse().ok(),
435 }
436 }
437}
438
439impl Display for Configuration {
440 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
441 match self {
442 Configuration::Unsigned(unsigned) => unsigned.fmt(f),
443 Configuration::Signed(signed) => signed.fmt(f),
444 Configuration::String(string) => string.fmt(f),
445 }
446 }
447}
448
449impl From<u64> for Configuration {
450 fn from(value: u64) -> Self {
451 Self::Unsigned(value)
452 }
453}
454
455impl From<i64> for Configuration {
456 fn from(value: i64) -> Self {
457 Self::Signed(value)
458 }
459}
460
461impl From<String> for Configuration {
462 fn from(value: String) -> Self {
463 Self::String(value)
464 }
465}
466
467impl<'a> From<&'a str> for Configuration {
468 fn from(value: &'a str) -> Self {
469 Self::String(value.to_string())
470 }
471}
472
473#[derive(Default, Debug, Clone, Serialize, Deserialize)]
475pub struct ResourceName<'a>(Vec<Identifier<'a>>);
476
477impl<'a> ResourceName<'a> {
478 #[must_use]
480 pub fn to_owned(&self) -> ResourceName<'static> {
481 ResourceName(self.0.iter().map(Identifier::to_owned).collect())
482 }
483}
484
485impl<'a> Display for ResourceName<'a> {
486 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
487 for (index, identifier) in self.0.iter().enumerate() {
488 if index > 0 {
489 f.write_char('.')?;
490 }
491
492 identifier.fmt(f)?;
493 }
494
495 Ok(())
496 }
497}
498
499impl<'a> ResourceName<'a> {
500 #[must_use]
502 pub fn any() -> Self {
503 Self::named(Identifier::Any)
504 }
505
506 #[must_use]
508 pub fn named<I: Into<Identifier<'a>>>(name: I) -> Self {
509 Self(vec![name.into()])
510 }
511
512 #[must_use]
514 pub fn and<I: Into<Identifier<'a>>>(mut self, name: I) -> Self {
515 self.0.push(name.into());
516 self
517 }
518}
519
520impl<'a> AsRef<[Identifier<'a>]> for ResourceName<'a> {
521 fn as_ref(&self) -> &[Identifier<'a>] {
522 &self.0
523 }
524}
525
526impl<'a> IntoIterator for ResourceName<'a> {
527 type IntoIter = std::vec::IntoIter<Identifier<'a>>;
528 type Item = Identifier<'a>;
529
530 fn into_iter(self) -> Self::IntoIter {
531 self.0.into_iter()
532 }
533}
534
535impl<'b, 'a> From<&'b [Identifier<'a>]> for ResourceName<'a> {
536 fn from(parts: &'b [Identifier<'a>]) -> Self {
537 Self(parts.to_vec())
538 }
539}
540
541impl<'a> From<&'a str> for ResourceName<'a> {
542 fn from(name: &'a str) -> Self {
543 Self(vec![Identifier::from(name)])
544 }
545}
546
547impl<'a> From<u64> for ResourceName<'a> {
548 fn from(name: u64) -> Self {
549 Self(vec![Identifier::from(name)])
550 }
551}