1use std::ops::Deref;
2
3use ps_hash::hash;
4use rancor::{Error, Strategy};
5use rkyv::{
6 api::high::HighSerializer,
7 bytecheck::CheckBytes,
8 ser::allocator::ArenaHandle,
9 util::AlignedVec,
10 validation::{archive::ArchiveValidator, shared::SharedValidator, Validator},
11 Archive, Serialize,
12};
13
14use crate::{Arc, DataChunk, Hash, Result};
15
16#[derive(Debug, Clone)]
17pub struct AlignedDataChunk {
18 data: AlignedVec,
19 hash: Arc<Hash>,
20}
21
22impl AlignedDataChunk {
23 pub fn from_parts<D, H>(data: D, hash: H) -> Self
24 where
25 D: Into<AlignedVec>,
26 H: Into<Arc<Hash>>,
27 {
28 let data = data.into();
29 let hash = hash.into();
30
31 Self { data, hash }
32 }
33
34 pub fn from_data_vec(data: AlignedVec) -> Result<Self> {
35 let hash = hash(&data)?;
36
37 Ok(Self::from_parts(data, hash))
38 }
39
40 #[must_use]
41 pub fn is_empty(&self) -> bool {
42 self.data.is_empty()
43 }
44
45 #[must_use]
46 pub fn len(&self) -> usize {
47 self.data.len()
48 }
49}
50
51impl AsRef<[u8]> for AlignedDataChunk {
52 fn as_ref(&self) -> &[u8] {
53 self
54 }
55}
56
57impl Deref for AlignedDataChunk {
58 type Target = [u8];
59
60 fn deref(&self) -> &Self::Target {
61 &self.data
62 }
63}
64
65impl AlignedDataChunk {
66 pub fn try_from<T>(value: &T) -> Result<Self>
67 where
68 for<'a> T: Archive + Serialize<HighSerializer<AlignedVec, ArenaHandle<'a>, Error>>,
69 {
70 let data = rkyv::to_bytes::<Error>(value)
71 .map_err(|err| crate::PsDataChunkError::RkyvSerializationFailed(err.into()))?;
72
73 Self::from_data_vec(data)
74 }
75
76 pub fn try_bytes_as<T: rkyv::Archive>(data: &[u8]) -> Result<&T::Archived>
77 where
78 for<'a> <T as rkyv::Archive>::Archived:
79 CheckBytes<Strategy<Validator<ArchiveValidator<'a>, SharedValidator>, rancor::Error>>,
80 {
81 rkyv::access::<T::Archived, Error>(data)
82 .map_err(|err| crate::PsDataChunkError::RkyvInvalidArchive(err.into()))
83 }
84
85 pub fn try_as<T: rkyv::Archive>(&self) -> Result<&T::Archived>
86 where
87 for<'a> <T as Archive>::Archived:
88 CheckBytes<Strategy<Validator<ArchiveValidator<'a>, SharedValidator>, rancor::Error>>,
89 {
90 Self::try_bytes_as::<T>(self.data_ref())
91 }
92}
93
94impl DataChunk for AlignedDataChunk {
95 fn data_ref(&self) -> &[u8] {
96 self
97 }
98 fn hash_ref(&self) -> &Hash {
99 &self.hash
100 }
101 fn hash(&self) -> Arc<Hash> {
102 self.hash.clone()
103 }
104
105 fn into_owned(self) -> crate::OwnedDataChunk {
107 let Self { data, hash } = self;
108
109 crate::OwnedDataChunk::from_data_and_hash(data, hash)
110 }
111}