1pub mod aligned;
2pub mod borrowed;
3pub mod encrypted;
4pub mod error;
5pub mod mbuf;
6pub mod owned;
7pub mod serialized;
8pub mod shared;
9pub mod typed;
10pub mod utils;
11pub use aligned::AlignedDataChunk;
12pub use borrowed::BorrowedDataChunk;
13pub use encrypted::EncryptedDataChunk;
14pub use error::PsDataChunkError;
15pub use error::Result;
16pub use mbuf::MbufDataChunk;
17pub use owned::OwnedDataChunk;
18pub use ps_hash::Hash;
19pub use ps_mbuf::Mbuf;
20pub use serialized::SerializedDataChunk;
21pub use shared::SharedDataChunk;
22pub use typed::ToDataChunk;
23pub use typed::ToTypedDataChunk;
24pub use typed::TypedDataChunk;
25
26use std::sync::Arc;
27
28pub trait DataChunkTrait {
30 fn data_ref(&self) -> &[u8];
31 fn hash_ref(&self) -> &[u8];
32
33 fn hash(&self) -> Arc<Hash> {
34 ps_hash::hash(self.data_ref()).into()
35 }
36
37 fn encrypt(&self) -> Result<EncryptedDataChunk> {
38 self.serialize()?.encrypt()
39 }
40
41 fn decrypt(&self, key: &[u8]) -> Result<SerializedDataChunk> {
42 utils::decrypt(self.data_ref(), key)
43 }
44
45 fn to_datachunk(&self) -> DataChunk {
46 DataChunk::Borrowed(self.borrow())
47 }
48
49 fn borrow(&self) -> BorrowedDataChunk {
50 BorrowedDataChunk::from_parts(self.data_ref(), self.hash())
51 }
52
53 fn to_owned(&self) -> OwnedDataChunk {
54 let data_ref = self.data_ref();
55 let reserved_size = utils::offsets(data_ref.len()).2;
56 let mut data_vec = Vec::with_capacity(reserved_size);
57
58 data_vec.extend_from_slice(data_ref);
59
60 OwnedDataChunk::from_parts(data_vec, self.hash())
61 }
62
63 fn serialize(&self) -> Result<SerializedDataChunk> {
64 SerializedDataChunk::from_parts(self.data_ref(), self.hash())
65 }
66
67 fn try_as<T: rkyv::Archive>(&self) -> Result<TypedDataChunk<T>>
68 where
69 T::Archived:
70 for<'a> rkyv::bytecheck::CheckBytes<rkyv::api::high::HighValidator<'a, rancor::Error>>,
71 {
72 match typed::check_byte_layout::<T>(self.data_ref()) {
73 true => Ok(unsafe { TypedDataChunk::from_chunk_unchecked(self.to_datachunk()) }),
74 false => Err(PsDataChunkError::TypeError),
75 }
76 }
77}
78
79pub enum DataChunk<'lt> {
81 Aligned(AlignedDataChunk),
82 Borrowed(BorrowedDataChunk<'lt>),
83 Mbuf(MbufDataChunk<'lt>),
84 Owned(OwnedDataChunk),
85 Serialized(SerializedDataChunk),
86 Shared(SharedDataChunk),
87}
88
89impl<'lt> DataChunkTrait for DataChunk<'lt> {
90 fn data_ref(&self) -> &[u8] {
91 self.data_ref()
92 }
93 fn hash_ref(&self) -> &[u8] {
94 self.hash_ref()
95 }
96 fn hash(&self) -> Arc<Hash> {
97 self.hash()
98 }
99}
100
101impl<'lt> From<AlignedDataChunk> for DataChunk<'lt> {
102 fn from(chunk: AlignedDataChunk) -> Self {
103 Self::Aligned(chunk)
104 }
105}
106
107impl<'lt> From<BorrowedDataChunk<'lt>> for DataChunk<'lt> {
108 fn from(chunk: BorrowedDataChunk<'lt>) -> Self {
109 Self::Borrowed(chunk)
110 }
111}
112
113impl<'lt> From<MbufDataChunk<'lt>> for DataChunk<'lt> {
114 fn from(chunk: MbufDataChunk<'lt>) -> Self {
115 Self::Mbuf(chunk)
116 }
117}
118
119impl<'lt> From<OwnedDataChunk> for DataChunk<'lt> {
120 fn from(chunk: OwnedDataChunk) -> Self {
121 Self::Owned(chunk)
122 }
123}
124
125impl<'lt> DataChunk<'lt> {
126 pub fn data_ref(&self) -> &[u8] {
127 match self {
128 Self::Borrowed(borrowed) => borrowed.data_ref(),
129 Self::Aligned(aligned) => aligned.data_ref(),
130 Self::Mbuf(mbuf) => mbuf.data_ref(),
131 Self::Owned(owned) => owned.data_ref(),
132 Self::Serialized(serialized) => serialized.data_ref(),
133 Self::Shared(shared) => shared.data_ref(),
134 }
135 }
136
137 pub fn hash_ref(&self) -> &[u8] {
138 match self {
139 Self::Aligned(aligned) => aligned.hash_ref(),
140 Self::Borrowed(borrowed) => borrowed.hash_ref(),
141 Self::Mbuf(mbuf) => mbuf.hash_ref(),
142 Self::Owned(owned) => owned.hash_ref(),
143 Self::Serialized(serialized) => serialized.hash_ref(),
144 Self::Shared(shared) => shared.hash_ref(),
145 }
146 }
147
148 pub fn hash(&self) -> Arc<Hash> {
149 match self {
150 Self::Aligned(aligned) => aligned.hash(),
151 Self::Borrowed(borrowed) => borrowed.hash(),
152 Self::Mbuf(mbuf) => mbuf.hash(),
153 Self::Owned(owned) => owned.hash(),
154 Self::Serialized(serialized) => serialized.hash(),
155 Self::Shared(shared) => shared.hash(),
156 }
157 }
158
159 #[inline(always)]
160 pub fn decrypt(&self, key: &[u8]) -> Result<SerializedDataChunk> {
162 let decrypted = match self {
163 Self::Borrowed(borrowed) => borrowed.decrypt(key),
164 Self::Mbuf(mbuf) => mbuf.decrypt(key),
165 Self::Owned(chunk) => chunk.decrypt(key),
166 Self::Aligned(aligned) => aligned.decrypt(key),
167 Self::Serialized(serialized) => serialized.decrypt(key),
168 Self::Shared(shared) => shared.decrypt(key),
169 }?;
170
171 Ok(decrypted)
172 }
173
174 #[inline(always)]
175 pub fn encrypt(&self) -> Result<EncryptedDataChunk> {
177 match self {
178 DataChunk::Owned(owned) => owned.encrypt(),
179 DataChunk::Aligned(aligned) => {
180 OwnedDataChunk::encrypt_serialized_bytes(aligned.serialize()?.serialized_bytes())
181 }
182 DataChunk::Serialized(serialized) => serialized.encrypt(),
183 DataChunk::Shared(shared) => shared.encrypt(),
184 _ => self.serialize()?.encrypt(),
185 }
186 }
187
188 #[inline(always)]
189 pub fn encrypt_mut(&mut self) -> Result<EncryptedDataChunk> {
191 match self {
192 DataChunk::Owned(chunk) => chunk.encrypt_mut(),
193 _ => self.encrypt(),
194 }
195 }
196
197 pub fn guarantee_alignment<T>(self) -> Result<DataChunk<'lt>> {
198 let align_size = std::mem::align_of::<T>();
199 let remainder = self.data_ref().as_ptr() as usize % align_size;
200
201 let chunk = if remainder == 0 {
202 self
203 } else {
204 DataChunk::Serialized(self.serialize()?)
205 };
206
207 Ok(chunk)
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214
215 #[test]
216 fn test_encryption_decryption() -> Result<()> {
217 let original_data = "Neboť tak Bůh miluje svět, že dal [svého] jediného Syna, aby žádný, kdo v něho věří, nezahynul, ale měl život věčný. Vždyť Bůh neposlal [svého] Syna na svět, aby svět odsoudil, ale aby byl svět skrze něj zachráněn.".as_bytes().to_owned();
218
219 let data_chunk = DataChunk::Owned(OwnedDataChunk::from_data_ref(&original_data));
220
221 let encrypted_chunk = data_chunk.encrypt()?;
222 let decrypted_chunk = encrypted_chunk.decrypt()?;
223
224 assert_eq!(decrypted_chunk.data_ref(), original_data);
225
226 Ok(())
227 }
228
229 #[test]
230 fn test_serialization() -> Result<()> {
231 let original_data = vec![1, 2, 3, 4, 5];
232 let hash = ps_hash::hash(&original_data).into();
233 let owned_chunk = OwnedDataChunk::from_parts(original_data.to_vec(), hash);
234 let data_chunk = DataChunk::Owned(owned_chunk);
235
236 let serialized = data_chunk.serialize()?;
237 let deserialized = OwnedDataChunk::deserialize(&serialized.into_buffer())?;
238
239 assert_eq!(deserialized.data_ref(), original_data);
240
241 Ok(())
242 }
243}