vortex_array/
metadata.rs

1use std::fmt::{Debug, Formatter};
2
3use flexbuffers::FlexbufferSerializer;
4use vortex_error::{VortexError, VortexExpect, VortexResult, vortex_bail, vortex_err};
5
6pub trait SerializeMetadata {
7    fn serialize(&self) -> Option<Vec<u8>>;
8}
9
10impl SerializeMetadata for () {
11    fn serialize(&self) -> Option<Vec<u8>> {
12        None
13    }
14}
15
16pub trait DeserializeMetadata
17where
18    Self: Sized,
19{
20    type Output;
21
22    fn deserialize(metadata: Option<&[u8]>) -> VortexResult<Self::Output>;
23
24    /// Deserialize metadata without validation.
25    ///
26    /// ## Safety
27    ///
28    /// Those who use this API must be sure to have invoked deserialize at least once before
29    /// calling this method.
30    unsafe fn deserialize_unchecked(metadata: Option<&[u8]>) -> Self::Output {
31        Self::deserialize(metadata)
32            .vortex_expect("Metadata should have been validated before calling this method")
33    }
34
35    /// Format metadata for display.
36    fn format(metadata: Option<&[u8]>, f: &mut Formatter<'_>) -> std::fmt::Result;
37}
38
39/// Empty array metadata
40#[derive(Debug)]
41pub struct EmptyMetadata;
42
43impl SerializeMetadata for EmptyMetadata {
44    fn serialize(&self) -> Option<Vec<u8>> {
45        None
46    }
47}
48
49impl DeserializeMetadata for EmptyMetadata {
50    type Output = EmptyMetadata;
51
52    fn deserialize(metadata: Option<&[u8]>) -> VortexResult<Self::Output> {
53        if metadata.is_some() {
54            vortex_bail!("EmptyMetadata should not have metadata bytes")
55        }
56        Ok(EmptyMetadata)
57    }
58
59    fn format(_metadata: Option<&[u8]>, f: &mut Formatter<'_>) -> std::fmt::Result {
60        f.write_str("EmptyMetadata")
61    }
62}
63
64/// A utility wrapper for automating the serialization of metadata using [rkyv](https://docs.rs/rkyv/latest/rkyv/).
65pub struct RkyvMetadata<M>(pub M);
66
67impl<M> SerializeMetadata for RkyvMetadata<M>
68where
69    M: for<'a> rkyv::Serialize<
70            rkyv::api::high::HighSerializer<
71                rkyv::util::AlignedVec,
72                rkyv::ser::allocator::ArenaHandle<'a>,
73                VortexError,
74            >,
75        >,
76{
77    fn serialize(&self) -> Option<Vec<u8>> {
78        let buf = rkyv::to_bytes::<VortexError>(&self.0)
79            .vortex_expect("Failed to serialize metadata using rkyv");
80        if buf.is_empty() {
81            None
82        } else {
83            Some(buf.to_vec())
84        }
85    }
86}
87
88impl<M: Debug> Debug for RkyvMetadata<M> {
89    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
90        self.0.fmt(f)
91    }
92}
93
94// TODO(ngates): this is slightly naive and more expensive than necessary.
95//  Many cases could use rkyv access instead of deserialize, which allows partial zero-copy
96//  access to the metadata. That said... our intention is to move towards u64 metadata, in which
97//  case the cost is negligible.
98impl<M> DeserializeMetadata for RkyvMetadata<M>
99where
100    M: Debug,
101    M: rkyv::Archive,
102    M::Archived:
103        for<'a> rkyv::bytecheck::CheckBytes<rkyv::api::high::HighValidator<'a, VortexError>>,
104    // Safe deserialization requires a pool
105    M::Archived: rkyv::Deserialize<M, rkyv::rancor::Strategy<rkyv::de::Pool, VortexError>>,
106    // Unsafe deserialization doesn't require a pool.
107    M::Archived: rkyv::Deserialize<M, rkyv::rancor::Strategy<(), VortexError>>,
108{
109    type Output = M;
110
111    fn deserialize(metadata: Option<&[u8]>) -> VortexResult<Self::Output> {
112        rkyv::from_bytes::<M, VortexError>(
113            metadata.ok_or_else(|| vortex_err!("Missing expected metadata"))?,
114        )
115    }
116
117    unsafe fn deserialize_unchecked(metadata: Option<&[u8]>) -> Self::Output {
118        unsafe {
119            rkyv::api::low::from_bytes_unchecked(
120                metadata.vortex_expect("Missing expected metadata"),
121            )
122            .vortex_expect("Failed to deserialize metadata")
123        }
124    }
125
126    #[allow(clippy::use_debug)]
127    fn format(metadata: Option<&[u8]>, f: &mut Formatter<'_>) -> std::fmt::Result {
128        match Self::deserialize(metadata) {
129            Ok(m) => write!(f, "{:?}", m),
130            Err(_) => write!(f, "Failed to deserialize metadata"),
131        }
132    }
133}
134
135/// A utility wrapper for automating the serialization of metadata using [serde](docs.rs/serde) into [flexbuffers](https://docs.rs/flexbuffers/latest/flexbuffers/).
136pub struct SerdeMetadata<M>(pub M);
137
138impl<M> SerializeMetadata for SerdeMetadata<M>
139where
140    M: serde::Serialize,
141{
142    fn serialize(&self) -> Option<Vec<u8>> {
143        let mut ser = FlexbufferSerializer::new();
144        serde::Serialize::serialize(&self.0, &mut ser)
145            .vortex_expect("Failed to serialize metadata using serde");
146        Some(ser.take_buffer())
147    }
148}
149
150impl<M> DeserializeMetadata for SerdeMetadata<M>
151where
152    M: Debug,
153    M: for<'m> serde::Deserialize<'m>,
154{
155    type Output = M;
156
157    fn deserialize(metadata: Option<&[u8]>) -> VortexResult<Self::Output> {
158        let bytes =
159            metadata.ok_or_else(|| vortex_err!("Serde metadata requires metadata bytes"))?;
160        Ok(M::deserialize(flexbuffers::Reader::get_root(bytes)?)?)
161    }
162
163    #[allow(clippy::use_debug)]
164    fn format(metadata: Option<&[u8]>, f: &mut Formatter<'_>) -> std::fmt::Result {
165        match Self::deserialize(metadata) {
166            Ok(m) => write!(f, "{:?}", m),
167            Err(_) => write!(f, "Failed to deserialize metadata"),
168        }
169    }
170}
171
172impl<M: Debug> Debug for SerdeMetadata<M> {
173    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
174        self.0.fmt(f)
175    }
176}