reifydb_type/value/blob/
base58.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the MIT, see license.md file
3
4use super::Blob;
5use crate::{Error, Fragment, error::diagnostic::blob, util::base58};
6
7impl Blob {
8	pub fn from_b58(fragment: Fragment) -> Result<Self, Error> {
9		let fragment = fragment;
10		let b58_str = fragment.text();
11		match base58::decode(b58_str) {
12			Ok(bytes) => Ok(Blob::new(bytes)),
13			Err(_) => Err(Error(blob::invalid_base58_string(fragment))),
14		}
15	}
16
17	pub fn to_b58(&self) -> String {
18		base58::encode(self.as_bytes())
19	}
20}
21
22#[cfg(test)]
23mod tests {
24	use super::*;
25	use crate::Fragment;
26
27	#[test]
28	fn test_from_b58() {
29		let blob = Blob::from_b58(Fragment::testing("9Ajdvzr")).unwrap();
30		assert_eq!(blob.as_bytes(), b"Hello");
31	}
32
33	#[test]
34	fn test_from_b58_empty() {
35		let blob = Blob::from_b58(Fragment::testing("")).unwrap();
36		assert_eq!(blob.as_bytes(), b"");
37	}
38
39	#[test]
40	fn test_from_b58_invalid() {
41		// '0', 'O', 'I', 'l' are not in base58 alphabet
42		let result = Blob::from_b58(Fragment::testing("0invalid"));
43		assert!(result.is_err());
44
45		let result = Blob::from_b58(Fragment::testing("Oops"));
46		assert!(result.is_err());
47
48		let result = Blob::from_b58(Fragment::testing("Invalid!"));
49		assert!(result.is_err());
50	}
51
52	#[test]
53	fn test_to_b58() {
54		let blob = Blob::new(b"Hello".to_vec());
55		assert_eq!(blob.to_b58(), "9Ajdvzr");
56	}
57
58	#[test]
59	fn test_to_b58_empty() {
60		let blob = Blob::new(vec![]);
61		assert_eq!(blob.to_b58(), "");
62	}
63
64	#[test]
65	fn test_b58_roundtrip() {
66		let original = b"Hello, World! \x00\x01\x02\xFF";
67		let blob = Blob::new(original.to_vec());
68		let b58_str = blob.to_b58();
69		let decoded = Blob::from_b58(Fragment::testing(&b58_str)).unwrap();
70		assert_eq!(decoded.as_bytes(), original);
71	}
72
73	#[test]
74	fn test_b58_binary_data() {
75		let data = vec![0xde, 0xad, 0xbe, 0xef];
76		let blob = Blob::new(data.clone());
77		let b58_str = blob.to_b58();
78		let decoded = Blob::from_b58(Fragment::testing(&b58_str)).unwrap();
79		assert_eq!(decoded.as_bytes(), &data);
80	}
81
82	#[test]
83	fn test_b58_leading_zeros() {
84		// Leading zero bytes become leading '1's
85		let data = vec![0, 0, 1];
86		let blob = Blob::new(data.clone());
87		let b58_str = blob.to_b58();
88		assert_eq!(b58_str, "112");
89		let decoded = Blob::from_b58(Fragment::testing(&b58_str)).unwrap();
90		assert_eq!(decoded.as_bytes(), &data);
91	}
92}