1use base64::Engine;
6use prost::bytes::Bytes;
7
8use crate::error::CoreError;
9
10pub fn decode_base64(input: &str) -> Result<Vec<u8>, CoreError> {
18 base64::engine::general_purpose::STANDARD
19 .decode(input.trim())
20 .map_err(|e| CoreError::InvalidBase64(e.to_string()))
21}
22
23pub fn decode_base64_bytes(input: &str) -> Result<Bytes, CoreError> {
31 decode_base64(input).map(Bytes::from)
32}
33
34pub fn decode_optional_base64(input: Option<&str>) -> Result<Option<Bytes>, CoreError> {
42 match input {
43 Some(s) if !s.trim().is_empty() => decode_base64_bytes(s).map(Some),
44 _ => Ok(None),
45 }
46}
47
48pub fn decode_hex(input: &str) -> Result<Bytes, CoreError> {
56 hex::decode(input.trim())
57 .map(Bytes::from)
58 .map_err(|e| CoreError::InvalidHex(e.to_string()))
59}
60
61pub fn decode_optional_hex(input: Option<&str>) -> Result<Option<Bytes>, CoreError> {
69 match input {
70 Some(s) if !s.trim().is_empty() => decode_hex(s).map(Some),
71 _ => Ok(None),
72 }
73}
74
75pub fn decode_base64_or_hex(input: &str) -> Result<Bytes, CoreError> {
95 match base64::engine::general_purpose::STANDARD.decode(input.trim()) {
97 Ok(bytes) => Ok(Bytes::from(bytes)),
98 Err(_) => decode_hex(input),
99 }
100}
101
102pub fn filter_username(username: Option<&str>) -> Option<&str> {
112 username.map(str::trim).filter(|s| !s.is_empty())
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_decode_base64() {
121 let encoded = "SGVsbG8gV29ybGQ="; let decoded = decode_base64(encoded).unwrap();
123 assert_eq!(decoded, b"Hello World");
124 }
125
126 #[test]
127 fn test_decode_base64_invalid() {
128 let result = decode_base64("not-valid-base64!!!");
129 assert!(result.is_err());
130 }
131
132 #[test]
133 fn test_decode_hex() {
134 let encoded = "48656c6c6f"; let decoded = decode_hex(encoded).unwrap();
136 assert_eq!(decoded.as_ref(), b"Hello");
137 }
138
139 #[test]
140 fn test_decode_hex_invalid() {
141 let result = decode_hex("not-valid-hex");
142 assert!(result.is_err());
143 }
144
145 #[test]
146 fn test_decode_base64_or_hex_base64() {
147 let encoded = "SGVsbG8="; let decoded = decode_base64_or_hex(encoded).unwrap();
149 assert_eq!(decoded.as_ref(), b"Hello");
150 }
151
152 #[test]
153 fn test_decode_base64_or_hex_hex() {
154 let encoded = "48656c6c6f"; let decoded = decode_base64_or_hex(encoded).unwrap();
156 assert_eq!(decoded.as_ref(), b"Hello");
157 }
158
159 #[test]
160 fn test_decode_optional_base64_none() {
161 let result = decode_optional_base64(None).unwrap();
162 assert!(result.is_none());
163 }
164
165 #[test]
166 fn test_decode_optional_base64_empty() {
167 let result = decode_optional_base64(Some("")).unwrap();
168 assert!(result.is_none());
169 }
170
171 #[test]
172 fn test_decode_optional_hex_none() {
173 let result = decode_optional_hex(None).unwrap();
174 assert!(result.is_none());
175 }
176
177 #[test]
178 fn test_decode_base64_or_hex_ambiguity() {
179 let decoded = decode_base64_or_hex("AABB").unwrap();
183 assert_eq!(decoded.as_ref(), &[0x00, 0x00, 0x41]);
185 assert_ne!(decoded.as_ref(), &[0xAA, 0xBB]);
186 }
187
188 #[test]
189 fn test_filter_username_valid() {
190 let result = filter_username(Some("user123"));
191 assert_eq!(result, Some("user123"));
192 }
193
194 #[test]
195 fn test_filter_username_empty() {
196 let result = filter_username(Some(""));
197 assert_eq!(result, None);
198 }
199
200 #[test]
201 fn test_filter_username_whitespace() {
202 let result = filter_username(Some(" "));
203 assert_eq!(result, None);
204 }
205
206 #[test]
207 fn test_filter_username_none() {
208 let result = filter_username(None);
209 assert_eq!(result, None);
210 }
211}