reifydb_type/value/blob/
mod.rs

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