Skip to main content

reifydb_type/value/blob/
hex.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use super::Blob;
5use crate::{
6	error::{BlobEncodingKind, Error, TypeError},
7	fragment::Fragment,
8	util::hex::{decode, encode},
9};
10
11impl Blob {
12	pub fn from_hex(fragment: Fragment) -> Result<Self, Error> {
13		let hex_str = fragment.text();
14		let clean_hex = if hex_str.starts_with("0x") || hex_str.starts_with("0X") {
15			&hex_str[2..]
16		} else {
17			hex_str
18		};
19
20		match decode(clean_hex) {
21			Ok(bytes) => Ok(Blob::new(bytes)),
22			Err(_) => Err(TypeError::BlobEncoding {
23				kind: BlobEncodingKind::InvalidHex,
24				message: format!("Invalid hexadecimal string: '{}'", fragment.text()),
25				fragment,
26			}
27			.into()),
28		}
29	}
30
31	pub fn to_hex(&self) -> String {
32		format!("0x{}", encode(self.as_bytes()))
33	}
34}
35
36#[cfg(test)]
37pub mod tests {
38	use super::*;
39	use crate::fragment::Fragment;
40
41	#[test]
42	fn test_from_hex() {
43		let blob = Blob::from_hex(Fragment::testing("48656c6c6f")).unwrap();
44		assert_eq!(blob.as_bytes(), b"Hello");
45	}
46
47	#[test]
48	fn test_from_hex_with_prefix() {
49		let blob = Blob::from_hex(Fragment::testing("0x48656c6c6f")).unwrap();
50		assert_eq!(blob.as_bytes(), b"Hello");
51
52		let blob = Blob::from_hex(Fragment::testing("0X48656c6c6f")).unwrap();
53		assert_eq!(blob.as_bytes(), b"Hello");
54	}
55
56	#[test]
57	fn test_from_hex_empty() {
58		let blob = Blob::from_hex(Fragment::testing("")).unwrap();
59		assert_eq!(blob.as_bytes(), b"");
60	}
61
62	#[test]
63	fn test_from_hex_invalid() {
64		let result = Blob::from_hex(Fragment::testing("xyz"));
65		assert!(result.is_err());
66
67		let result = Blob::from_hex(Fragment::testing("48656c6c6")); // odd length
68		assert!(result.is_err());
69	}
70
71	#[test]
72	fn test_to_hex() {
73		let blob = Blob::new(b"Hello".to_vec());
74		assert_eq!(blob.to_hex(), "0x48656c6c6f");
75	}
76
77	#[test]
78	fn test_hex_roundtrip() {
79		let original = b"Hello, World! \x00\x01\x02\xFF";
80		let blob = Blob::new(original.to_vec());
81		let hex_str = blob.to_hex();
82		let decoded = Blob::from_hex(Fragment::testing(&hex_str)).unwrap();
83		assert_eq!(decoded.as_bytes(), original);
84	}
85}