spacetimedb_sats/
bsatn.rs1use crate::buffer::{BufReader, BufWriter, CountWriter};
2use crate::de::{BasicSmallVecVisitor, Deserialize, DeserializeSeed, Deserializer as _};
3use crate::ser::Serialize;
4use crate::{ProductValue, Typespace, WithTypespace};
5use ser::BsatnError;
6use smallvec::SmallVec;
7
8pub mod de;
9pub mod eq;
10pub mod ser;
11
12pub use de::Deserializer;
13pub use ser::Serializer;
14
15pub use crate::buffer::DecodeError;
16pub use ser::BsatnError as EncodeError;
17
18#[inline]
20pub fn to_writer<W: BufWriter, T: Serialize + ?Sized>(w: &mut W, value: &T) -> Result<(), EncodeError> {
21 value.serialize_into_bsatn(Serializer::new(w))
22}
23
24pub fn to_vec<T: Serialize + ?Sized>(value: &T) -> Result<Vec<u8>, EncodeError> {
26 let mut v = Vec::new();
27 to_writer(&mut v, value)?;
28 Ok(v)
29}
30
31pub fn to_len<T: Serialize + ?Sized>(value: &T) -> Result<usize, EncodeError> {
33 let mut writer = CountWriter::default();
34 to_writer(&mut writer, value)?;
35 Ok(writer.finish())
36}
37
38pub fn from_reader<'de, T: Deserialize<'de>>(reader: &mut impl BufReader<'de>) -> Result<T, DecodeError> {
40 T::deserialize(Deserializer::new(reader))
41}
42
43pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, DecodeError> {
45 from_reader(&mut &*bytes)
46}
47
48pub fn decode<'a, 'de, S: ?Sized>(
50 ty: &'a S,
51 bytes: &mut impl BufReader<'de>,
52) -> Result<<WithTypespace<'a, S> as DeserializeSeed<'de>>::Output, DecodeError>
53where
54 WithTypespace<'a, S>: DeserializeSeed<'de>,
55{
56 crate::WithTypespace::empty(ty).deserialize(Deserializer::new(bytes))
57}
58
59macro_rules! codec_funcs {
60 ($ty:ty) => {
61 impl $ty {
62 pub fn decode<'a>(bytes: &mut impl BufReader<'a>) -> Result<Self, DecodeError> {
63 from_reader(bytes)
64 }
65
66 pub fn encode(&self, bytes: &mut impl BufWriter) {
67 to_writer(bytes, self).unwrap()
68 }
69 }
70 };
71 (val: $ty:ty) => {
72 impl $ty {
73 pub fn decode<'a>(
75 ty: &<Self as crate::Value>::Type,
76 bytes: &mut impl BufReader<'a>,
77 ) -> Result<Self, DecodeError> {
78 decode(ty, bytes)
79 }
80
81 pub fn decode_smallvec<'a>(
83 ty: &<Self as crate::Value>::Type,
84 bytes: &mut impl BufReader<'a>,
85 ) -> Result<SmallVec<[Self; 1]>, DecodeError> {
86 Deserializer::new(bytes).deserialize_array_seed(
87 BasicSmallVecVisitor,
88 crate::WithTypespace::new(&Typespace::new(Vec::new()), ty),
89 )
90 }
91
92 pub fn encode(&self, bytes: &mut impl BufWriter) {
93 to_writer(bytes, self).unwrap()
94 }
95 }
96 };
97}
98
99codec_funcs!(crate::AlgebraicType);
100codec_funcs!(crate::ProductType);
101codec_funcs!(crate::SumType);
102codec_funcs!(crate::ProductTypeElement);
103codec_funcs!(crate::SumTypeVariant);
104
105codec_funcs!(val: crate::AlgebraicValue);
106codec_funcs!(val: crate::ProductValue);
107codec_funcs!(val: crate::SumValue);
108
109pub trait ToBsatn {
115 fn to_bsatn_vec(&self) -> Result<Vec<u8>, BsatnError>;
117
118 fn to_bsatn_extend(&self, buf: &mut Vec<u8>) -> Result<(), BsatnError>;
121
122 fn static_bsatn_size(&self) -> Option<u16>;
126}
127
128impl<T: ToBsatn> ToBsatn for &T {
129 fn to_bsatn_vec(&self) -> Result<Vec<u8>, BsatnError> {
130 T::to_bsatn_vec(*self)
131 }
132 fn to_bsatn_extend(&self, buf: &mut Vec<u8>) -> Result<(), BsatnError> {
133 T::to_bsatn_extend(*self, buf)
134 }
135 fn static_bsatn_size(&self) -> Option<u16> {
136 T::static_bsatn_size(*self)
137 }
138}
139
140impl ToBsatn for ProductValue {
141 fn to_bsatn_vec(&self) -> Result<Vec<u8>, BsatnError> {
142 to_vec(self)
143 }
144
145 fn to_bsatn_extend(&self, buf: &mut Vec<u8>) -> Result<(), BsatnError> {
146 to_writer(buf, self)
147 }
148
149 fn static_bsatn_size(&self) -> Option<u16> {
150 None
151 }
152}
153
154mod private_is_primitive_type {
155 pub trait Sealed {}
156}
157#[doc(hidden)]
164pub unsafe trait IsPrimitiveType: private_is_primitive_type::Sealed {}
165macro_rules! is_primitive_type {
166 ($($prim:ty),*) => {
167 $(
168 impl private_is_primitive_type::Sealed for $prim {}
169 unsafe impl IsPrimitiveType for $prim {}
171 )*
172 };
173}
174is_primitive_type!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, f32, f64);
175
176pub const fn assert_is_primitive_type<T: IsPrimitiveType>() {}
179
180#[cfg(test)]
181mod tests {
182 use super::{to_vec, DecodeError};
183 use crate::proptest::generate_typed_value;
184 use crate::{meta_type::MetaType, AlgebraicType, AlgebraicValue};
185 use proptest::prelude::*;
186 use proptest::proptest;
187
188 #[test]
189 fn type_to_binary_equivalent() {
190 check_type(&AlgebraicType::meta_type());
191 }
192
193 #[track_caller]
194 fn check_type(ty: &AlgebraicType) {
195 let mut through_value = Vec::new();
196 ty.as_value().encode(&mut through_value);
197 let mut direct = Vec::new();
198 ty.encode(&mut direct);
199 assert_eq!(direct, through_value);
200 }
201
202 proptest! {
203 #[test]
204 fn bsatn_enc_de_roundtrips((ty, val) in generate_typed_value()) {
205 let bytes = to_vec(&val).unwrap();
206 let val_decoded = AlgebraicValue::decode(&ty, &mut &bytes[..]).unwrap();
207 prop_assert_eq!(val, val_decoded);
208 }
209
210 #[test]
211 fn bsatn_non_zero_one_u8_aint_bool(val in 2u8..) {
212 let bytes = [val];
213 prop_assert_eq!(
214 AlgebraicValue::decode(&AlgebraicType::Bool, &mut &bytes[..]),
215 Err(DecodeError::InvalidBool(val))
216 );
217 }
218 }
219}