datacake_rpc/
view.rs

1use std::fmt::{Debug, Formatter};
2use std::mem;
3use std::ops::Deref;
4
5use rkyv::de::deserializers::SharedDeserializeMap;
6use rkyv::validation::validators::DefaultValidator;
7use rkyv::{AlignedVec, Archive, CheckBytes, Deserialize};
8
9#[derive(Debug, thiserror::Error)]
10#[error("View cannot be made for type with provided data.")]
11/// The data provided is unable to be presented as the archived version
12/// of the view type.
13pub struct InvalidView;
14
15/// A block of data that can be accessed as if it is the archived value `T`.
16///
17/// This allows for safe, true zero-copy deserialization avoiding unnecessary
18/// allocations if the situation does not require having an owned version of the value.
19pub struct DataView<T, D = AlignedVec>
20where
21    T: Archive,
22    T::Archived: 'static,
23    D: Deref<Target = [u8]> + Send + Sync,
24{
25    /// The owned buffer itself.
26    ///
27    /// This must live as long as the view derived from it.
28    data: D,
29
30    /// The view reference which lives as long as `data: D`.
31    view: &'static rkyv::Archived<T>,
32}
33
34impl<T, D> DataView<T, D>
35where
36    T: Archive,
37    T::Archived: CheckBytes<DefaultValidator<'static>> + 'static,
38    D: Deref<Target = [u8]> + Send + Sync,
39{
40    /// Creates a new view using a provided buffer.
41    pub(crate) fn using(data: D) -> Result<Self, InvalidView> {
42        // SAFETY:
43        //  This is safe as we own the data and keep it apart
44        //  of the view itself.
45        let extended_buf = unsafe { mem::transmute::<&[u8], &'static [u8]>(&data) };
46
47        let view =
48            rkyv::check_archived_root::<'_, T>(extended_buf).map_err(|_| InvalidView)?;
49
50        Ok(Self { data, view })
51    }
52
53    /// Gets the bytes representation of the dataview.
54    pub fn as_bytes(&self) -> &[u8] {
55        &self.data
56    }
57
58    /// Consumes the bytes representation of the dataview.
59    pub fn into_data(self) -> D {
60        self.data
61    }
62}
63
64impl<T, D> DataView<T, D>
65where
66    T: Archive,
67    T::Archived: Deserialize<T, SharedDeserializeMap> + 'static,
68    D: Deref<Target = [u8]> + Send + Sync,
69{
70    /// Deserializes the view into it's owned value T.
71    pub fn to_owned(&self) -> Result<T, InvalidView> {
72        self.view
73            .deserialize(&mut SharedDeserializeMap::default())
74            .map_err(|_| InvalidView)
75    }
76}
77
78impl<T, D> Clone for DataView<T, D>
79where
80    T: Archive,
81    T::Archived: CheckBytes<DefaultValidator<'static>> + Debug,
82    D: Deref<Target = [u8]> + Send + Sync + Clone,
83{
84    fn clone(&self) -> Self {
85        Self::using(self.data.clone()).expect("BUG: Valid data has become invalid?")
86    }
87}
88
89impl<T, D> Debug for DataView<T, D>
90where
91    T: Archive,
92    T::Archived: CheckBytes<DefaultValidator<'static>> + Debug,
93    D: Deref<Target = [u8]> + Send + Sync,
94{
95    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96        self.view.fmt(f)
97    }
98}
99
100impl<T, D> Deref for DataView<T, D>
101where
102    T: Archive,
103    T::Archived: CheckBytes<DefaultValidator<'static>>,
104    D: Deref<Target = [u8]> + Send + Sync,
105{
106    type Target = T::Archived;
107
108    fn deref(&self) -> &Self::Target {
109        self.view
110    }
111}
112
113impl<T, D> PartialEq for DataView<T, D>
114where
115    T: Archive,
116    T::Archived: CheckBytes<DefaultValidator<'static>> + PartialEq,
117    D: Deref<Target = [u8]> + Send + Sync,
118{
119    fn eq(&self, other: &Self) -> bool {
120        self.view == other.view
121    }
122}
123
124impl<T, D> PartialEq<T> for DataView<T, D>
125where
126    T: Archive,
127    T::Archived: CheckBytes<DefaultValidator<'static>> + PartialEq<T>,
128    D: Deref<Target = [u8]> + Send + Sync,
129{
130    fn eq(&self, other: &T) -> bool {
131        self.view == other
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use rkyv::{Archive, Deserialize, Serialize};
138
139    use super::*;
140
141    #[repr(C)]
142    #[derive(Serialize, Deserialize, Archive, PartialEq, Eq, Debug)]
143    #[archive(compare(PartialEq), check_bytes)]
144    #[archive_attr(derive(Debug, PartialEq, Eq))]
145    struct Demo {
146        a: String,
147        b: u64,
148    }
149
150    #[test]
151    fn test_view() {
152        let demo = Demo {
153            a: "Jello".to_string(),
154            b: 133,
155        };
156
157        let bytes = rkyv::to_bytes::<_, 1024>(&demo).unwrap();
158        let view: DataView<Demo, _> = DataView::using(bytes).unwrap();
159        assert!(view == demo, "Original and view must match.");
160    }
161
162    #[test]
163    fn test_invalid_view() {
164        let res = DataView::<Demo, _>::using(b"Hello, world!".to_vec());
165        assert!(res.is_err(), "View should be rejected");
166    }
167
168    #[test]
169    fn test_deserialize() {
170        let demo = Demo {
171            a: "Jello".to_string(),
172            b: 133,
173        };
174
175        let bytes = rkyv::to_bytes::<_, 1024>(&demo).unwrap();
176        let view: DataView<Demo, _> = DataView::using(bytes).unwrap();
177        assert!(view == demo, "Original and view must match.");
178
179        let value = view.to_owned().unwrap();
180        assert_eq!(value, demo, "Deserialized and original value should match.")
181    }
182}