Skip to main content

reifydb_type/value/blob/
base58.rs

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