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