reifydb_type/value/blob/
base64.rs1use super::Blob;
5use crate::{Error, IntoFragment, error::diagnostic::blob, util::base64::engine::general_purpose};
6
7impl Blob {
8 pub fn from_b64<'a>(fragment: impl IntoFragment<'a>) -> Result<Self, Error> {
9 let fragment = fragment.into_fragment();
10 let b64_str = fragment.text();
11 match general_purpose::STANDARD.decode(b64_str) {
13 Ok(bytes) => Ok(Blob::new(bytes)),
14 Err(_) => {
15 match general_purpose::STANDARD_NO_PAD.decode(b64_str) {
17 Ok(bytes) => Ok(Blob::new(bytes)),
18 Err(_) => Err(Error(blob::invalid_base64_string(fragment))),
19 }
20 }
21 }
22 }
23
24 pub fn from_b64url<'a>(fragment: impl IntoFragment<'a>) -> Result<Self, Error> {
25 let fragment = fragment.into_fragment();
26 let b64url_str = fragment.text();
27 match general_purpose::URL_SAFE_NO_PAD.decode(b64url_str) {
28 Ok(bytes) => Ok(Blob::new(bytes)),
29 Err(_) => Err(Error(blob::invalid_base64url_string(fragment))),
30 }
31 }
32
33 pub fn to_b64(&self) -> String {
34 general_purpose::STANDARD.encode(self.as_bytes())
35 }
36
37 pub fn to_b64url(&self) -> String {
38 general_purpose::URL_SAFE_NO_PAD.encode(self.as_bytes())
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use crate::OwnedFragment;
46
47 #[test]
48 fn test_from_b64() {
49 let blob = Blob::from_b64(OwnedFragment::testing("SGVsbG8=")).unwrap();
50 assert_eq!(blob.as_bytes(), b"Hello");
51 }
52
53 #[test]
54 fn test_from_b64_no_padding() {
55 let blob = Blob::from_b64(OwnedFragment::testing("SGVsbG8")).unwrap();
56 assert_eq!(blob.as_bytes(), b"Hello");
57 }
58
59 #[test]
60 fn test_from_b64_empty() {
61 let blob = Blob::from_b64(OwnedFragment::testing("")).unwrap();
62 assert_eq!(blob.as_bytes(), b"");
63 }
64
65 #[test]
66 fn test_from_b64_invalid() {
67 let result = Blob::from_b64(OwnedFragment::testing("!!!invalid!!!"));
68 assert!(result.is_err());
69 }
70
71 #[test]
72 fn test_from_b64url() {
73 let blob = Blob::from_b64url(OwnedFragment::testing("SGVsbG8")).unwrap();
74 assert_eq!(blob.as_bytes(), b"Hello");
75 }
76
77 #[test]
78 fn test_from_b64url_invalid() {
79 let result = Blob::from_b64url(OwnedFragment::testing("SGVsbG8=")); assert!(result.is_err());
81 }
82
83 #[test]
84 fn test_to_b64() {
85 let blob = Blob::new(b"Hello".to_vec());
86 assert_eq!(blob.to_b64(), "SGVsbG8=");
87 }
88
89 #[test]
90 fn test_to_b64url() {
91 let blob = Blob::new(b"Hello".to_vec());
92 assert_eq!(blob.to_b64url(), "SGVsbG8");
93 }
94
95 #[test]
96 fn test_b64_roundtrip() {
97 let original = b"Hello, World! \x00\x01\x02\xFF";
98 let blob = Blob::new(original.to_vec());
99 let b64_str = blob.to_b64();
100 let decoded = Blob::from_b64(OwnedFragment::testing(&b64_str)).unwrap();
101 assert_eq!(decoded.as_bytes(), original);
102 }
103
104 #[test]
105 fn test_b64url_roundtrip() {
106 let original = b"Hello, World! \x00\x01\x02\xFF";
107 let blob = Blob::new(original.to_vec());
108 let b64url_str = blob.to_b64url();
109 let decoded = Blob::from_b64url(OwnedFragment::testing(&b64url_str)).unwrap();
110 assert_eq!(decoded.as_bytes(), original);
111 }
112}