ps_datachunk/
aligned.rs

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    /// Transforms this chunk into an [`OwnedDataChunk`]
106    fn into_owned(self) -> crate::OwnedDataChunk {
107        let Self { data, hash } = self;
108
109        crate::OwnedDataChunk::from_data_and_hash(data, hash)
110    }
111}