scratchstack_aws_principal/
canonical_user.rs1use {
2 crate::PrincipalError,
3 std::fmt::{Display, Formatter, Result as FmtResult},
4};
5
6#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
10pub struct CanonicalUser {
11 canonical_user_id: String,
13}
14
15impl CanonicalUser {
16 pub fn new(canonical_user_id: &str) -> Result<Self, PrincipalError> {
33 if canonical_user_id.len() != 64 {
34 return Err(PrincipalError::InvalidCanonicalUserId(canonical_user_id.to_string()));
35 }
36
37 for c in canonical_user_id.bytes() {
38 if !matches!(c, b'0'..=b'9' | b'a'..=b'f') {
39 return Err(PrincipalError::InvalidCanonicalUserId(canonical_user_id.to_string()));
40 }
41 }
42
43 Ok(Self {
44 canonical_user_id: canonical_user_id.into(),
45 })
46 }
47
48 #[inline]
50 pub fn canonical_user_id(&self) -> &str {
51 &self.canonical_user_id
52 }
53}
54
55impl Display for CanonicalUser {
56 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
57 f.write_str(self.canonical_user_id())
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use {
64 super::CanonicalUser,
65 crate::{PrincipalIdentity, PrincipalSource},
66 std::{
67 collections::hash_map::DefaultHasher,
68 hash::{Hash, Hasher},
69 },
70 };
71
72 #[test]
73 fn check_components() {
74 let cu1a = CanonicalUser::new("9da4bcba2132ad952bba3c8ecb37e668d99b310ce313da30c98aba4cdf009a7d").unwrap();
75 assert_eq!(cu1a.canonical_user_id(), "9da4bcba2132ad952bba3c8ecb37e668d99b310ce313da30c98aba4cdf009a7d");
76
77 let p = PrincipalIdentity::from(cu1a);
78 let source = p.source();
79 assert_eq!(source, PrincipalSource::CanonicalUser);
80 assert_eq!(source.to_string(), "CanonicalUser".to_string());
81 }
82
83 #[test]
84 #[allow(clippy::redundant_clone)]
85 fn check_derived() {
86 let cu1a = CanonicalUser::new("0000000000000000000000000000000000000000000000000000000000000000").unwrap();
87 let cu1b = CanonicalUser::new("0000000000000000000000000000000000000000000000000000000000000000").unwrap();
88 let cu2 = CanonicalUser::new("0000000000000000000000000000000000000000000000000000000000000001").unwrap();
89 let cu3 = CanonicalUser::new("0000000000000000000000000000000000000000000000000000000000000002").unwrap();
90
91 assert_eq!(cu1a, cu1b);
92 assert_ne!(cu1a, cu2);
93 assert_eq!(cu1a.clone(), cu1a);
94
95 let mut h1a = DefaultHasher::new();
97 let mut h1b = DefaultHasher::new();
98 let mut h2 = DefaultHasher::new();
99 cu1a.hash(&mut h1a);
100 cu1b.hash(&mut h1b);
101 cu2.hash(&mut h2);
102 let hash1a = h1a.finish();
103 let hash1b = h1b.finish();
104 let hash2 = h2.finish();
105 assert_eq!(hash1a, hash1b);
106 assert_ne!(hash1a, hash2);
107
108 assert!(cu1a <= cu1b);
110 assert!(cu1a < cu2);
111 assert!(cu2 > cu1a);
112 assert!(cu2 < cu3);
113 assert!(cu3 > cu2);
114 assert!(cu3 > cu1a);
115
116 assert_eq!(cu1a.clone().max(cu2.clone()), cu2);
117 assert_eq!(cu1a.clone().min(cu2), cu1a);
118
119 let _ = format!("{cu1a:?}");
121 }
122
123 #[test]
124 fn check_valid_canonical_user() {
125 let cu1a = CanonicalUser::new("9da4bcba2132ad952bba3c8ecb37e668d99b310ce313da30c98aba4cdf009a7d").unwrap();
126 let cu1b = CanonicalUser::new("9da4bcba2132ad952bba3c8ecb37e668d99b310ce313da30c98aba4cdf009a7d").unwrap();
127 let cu2 = CanonicalUser::new("772183b840c93fe103e45cd24ca8b8c94425a373465c6eb535b7c4b9593811e5").unwrap();
128
129 assert_eq!(cu1a, cu1b);
130 assert_eq!(cu1a, cu1a.clone());
131 assert_ne!(cu1a, cu2);
132
133 assert_eq!(cu1a.to_string(), "9da4bcba2132ad952bba3c8ecb37e668d99b310ce313da30c98aba4cdf009a7d");
134 assert_eq!(cu2.to_string(), "772183b840c93fe103e45cd24ca8b8c94425a373465c6eb535b7c4b9593811e5");
135 }
136
137 #[test]
138 fn check_invalid_canonical_users() {
139 let err = CanonicalUser::new("123456789012345678901234567890123456789012345678901234567890123").unwrap_err();
140 assert_eq!(
141 err.to_string(),
142 r#"Invalid canonical user id: "123456789012345678901234567890123456789012345678901234567890123""#
143 );
144
145 let err = CanonicalUser::new("12345678901234567890123456789012345678901234567890123456789012345").unwrap_err();
146 assert_eq!(
147 err.to_string(),
148 r#"Invalid canonical user id: "12345678901234567890123456789012345678901234567890123456789012345""#
149 );
150
151 let err = CanonicalUser::new("123456789012345678901234567890123456789012345678901234567890AAAA").unwrap_err();
152 assert_eq!(
153 err.to_string(),
154 r#"Invalid canonical user id: "123456789012345678901234567890123456789012345678901234567890AAAA""#
155 );
156 }
157}
158