Skip to main content

reifydb_type/value/blob/
mod.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2025 ReifyDB
3
4use std::{
5	fmt::{Display, Formatter},
6	ops::Deref,
7};
8
9use serde::{Deserialize, Serialize};
10
11use crate::util;
12
13pub mod base58;
14pub mod base64;
15pub mod hex;
16pub mod utf8;
17
18/// A binary large object (BLOB) wrapper type
19#[repr(transparent)]
20#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
21pub struct Blob(Vec<u8>);
22
23impl Blob {
24	/// Create a new BLOB from raw bytes
25	pub fn new(bytes: Vec<u8>) -> Self {
26		Self(bytes)
27	}
28
29	pub fn empty() -> Self {
30		Self(Vec::with_capacity(0))
31	}
32
33	/// Create a BLOB from a byte slice
34	pub fn from_slice(bytes: &[u8]) -> Self {
35		Self(Vec::from(bytes.to_vec()))
36	}
37
38	/// Get the raw bytes
39	pub fn as_bytes(&self) -> &[u8] {
40		&self.0
41	}
42
43	/// Get the length in bytes
44	pub fn len(&self) -> usize {
45		self.0.len()
46	}
47
48	/// Check if the BLOB is empty
49	pub fn is_empty(&self) -> bool {
50		self.0.is_empty()
51	}
52
53	/// Convert into the inner bytes
54	pub fn into_bytes(self) -> Vec<u8> {
55		self.0.to_vec()
56	}
57}
58
59impl Deref for Blob {
60	type Target = [u8];
61
62	fn deref(&self) -> &Self::Target {
63		&self.0
64	}
65}
66
67impl From<Vec<u8>> for Blob {
68	fn from(bytes: Vec<u8>) -> Self {
69		Self::new(bytes)
70	}
71}
72
73impl From<&[u8]> for Blob {
74	fn from(bytes: &[u8]) -> Self {
75		Self::from_slice(bytes)
76	}
77}
78
79impl From<Blob> for Vec<u8> {
80	fn from(blob: Blob) -> Self {
81		blob.into_bytes()
82	}
83}
84
85impl Display for Blob {
86	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
87		write!(f, "0x{}", util::hex::encode(self.as_bytes()))
88	}
89}
90
91#[cfg(test)]
92pub mod tests {
93	use super::*;
94
95	#[test]
96	fn test_blob_from_bytes() {
97		let data = vec![0xDE, 0xAD, 0xBE, 0xEF];
98		let blob = Blob::new(data.clone());
99		assert_eq!(blob.as_bytes(), &data);
100		assert_eq!(blob.len(), 4);
101		assert!(!blob.is_empty());
102	}
103
104	#[test]
105	fn test_blob_from_slice() {
106		let data = [0xCA, 0xFE, 0xBA, 0xBE];
107		let blob = Blob::from_slice(&data);
108		assert_eq!(blob.as_bytes(), &data);
109	}
110
111	#[test]
112	fn test_blob_deref() {
113		let blob = Blob::new(vec![1, 2, 3]);
114		let bytes: &[u8] = &blob;
115		assert_eq!(bytes, &[1, 2, 3]);
116	}
117
118	#[test]
119	fn test_blob_conversions() {
120		let data = vec![0xFF, 0x00, 0xFF];
121		let blob = Blob::from(data.clone());
122		let bytes: Vec<u8> = blob.into();
123		assert_eq!(bytes, data);
124	}
125
126	#[test]
127	fn test_blob_display() {
128		let blob = Blob::new(vec![0xDE, 0xAD, 0xBE, 0xEF]);
129		assert_eq!(format!("{}", blob), "0xdeadbeef");
130
131		let empty_blob = Blob::new(vec![]);
132		assert_eq!(format!("{}", empty_blob), "0x");
133
134		let single_byte_blob = Blob::new(vec![0xFF]);
135		assert_eq!(format!("{}", single_byte_blob), "0xff");
136	}
137}