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