1use core::any::{TypeId, type_name};
7pub use cu29_value_types::{QuantityMetadata, TimeStorageUnit, ValueMetadata};
8
9pub trait ValueDecode: 'static + Sized {
19 const DECODE: &'static ValueDecodeSpec;
21
22 const METADATA: &'static [ValueMetadata] = &[];
27
28 #[doc(hidden)]
30 const __DECODE_REF: ValueDecodeRef = ValueDecodeRef {
31 describe: describe::<Self>,
32 };
33}
34
35#[derive(Clone, Copy, Debug)]
37pub struct ValueDecodeRef {
38 pub describe: fn() -> ValueDecodeType,
40}
41
42impl ValueDecodeRef {
43 pub const fn of<T: ValueDecode>() -> Self {
45 Self {
46 describe: describe::<T>,
47 }
48 }
49}
50
51fn describe<T: ValueDecode>() -> ValueDecodeType {
52 ValueDecodeType {
53 type_id: TypeId::of::<T>(),
54 type_name: type_name::<T>(),
55 spec: T::DECODE,
56 metadata: T::METADATA,
57 }
58}
59
60#[derive(Clone, Copy, Debug)]
62pub struct ValueDecodeType {
63 pub type_id: TypeId,
65 pub type_name: &'static str,
67 pub spec: &'static ValueDecodeSpec,
69 pub metadata: &'static [ValueMetadata],
71}
72
73pub use cu29_value_types::Scalar;
74
75#[derive(Clone, Copy, Debug)]
77pub enum FieldSelector {
78 Named(&'static str),
80 Index {
82 index: usize,
84 declared_fields: usize,
86 },
87}
88
89#[derive(Clone, Copy, Debug)]
91pub struct ValueDecodeField {
92 pub selector: FieldSelector,
94 pub declaration_index: usize,
96 pub value: ValueDecodeRef,
98}
99
100pub use cu29_value_types::RecordShape;
101
102#[derive(Clone, Copy, Debug)]
104pub struct ValueDecodeVariant {
105 pub tag: u32,
107 pub name: &'static str,
109 pub shape: RecordShape,
111 pub fields: &'static [ValueDecodeField],
113}
114
115#[derive(Clone, Copy, Debug)]
117pub enum ValueDecodeSpec {
118 Unit,
120 Scalar(Scalar),
122 String,
124 Bytes,
126 Record {
128 shape: RecordShape,
130 fields: &'static [ValueDecodeField],
132 },
133 Array {
135 element: ValueDecodeRef,
137 len: usize,
139 },
140 Sequence {
142 element: ValueDecodeRef,
144 count: Scalar,
146 capacity: Option<usize>,
148 },
149 Map {
151 key: ValueDecodeRef,
153 value: ValueDecodeRef,
155 },
156 Option(ValueDecodeRef),
158 Delegate(ValueDecodeRef),
160 Enum {
162 tag: Scalar,
164 variants: &'static [ValueDecodeVariant],
166 },
167}
168
169macro_rules! scalars {
170 ($($ty:ty => $scalar:ident),* $(,)?) => {$(
171 impl ValueDecode for $ty { const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Scalar(Scalar::$scalar); }
172 )*};
173}
174scalars!(bool=>Bool, u8=>U8, u16=>U16, u32=>U32, u64=>U64, u128=>U128,
175 i8=>I8, i16=>I16, i32=>I32, i64=>I64, i128=>I128, f32=>F32, f64=>F64, char=>Char,
176 usize=>U64, isize=>I64);
177impl ValueDecode for () {
178 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Unit;
179}
180impl<T: 'static> ValueDecode for core::marker::PhantomData<T> {
181 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Unit;
182}
183impl<T: ValueDecode, const N: usize> ValueDecode for [T; N] {
184 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Array {
185 element: ValueDecodeRef::of::<T>(),
186 len: N,
187 };
188}
189impl<T: ValueDecode> ValueDecode for Option<T> {
190 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Option(ValueDecodeRef::of::<T>());
191}
192impl<T: ValueDecode> ValueDecode for &'static T {
193 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Delegate(ValueDecodeRef::of::<T>());
194}
195impl ValueDecode for &'static str {
196 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::String;
197}
198impl<T: ValueDecode> ValueDecode for &'static [T] {
199 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence {
200 element: ValueDecodeRef::of::<T>(),
201 count: Scalar::U64,
202 capacity: None,
203 };
204}
205
206#[cfg(feature = "alloc")]
207mod allocated {
208 use super::*;
209 use alloc::{
210 boxed::Box,
211 collections::{BTreeMap, BTreeSet, VecDeque},
212 rc::Rc,
213 string::String,
214 sync::Arc,
215 vec::Vec,
216 };
217 impl ValueDecode for String {
218 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::String;
219 }
220 macro_rules! sequence { ($($container:ident),*) => {$(
221 impl<T: ValueDecode> ValueDecode for $container<T> {
222 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence { element: ValueDecodeRef::of::<T>(), count: Scalar::U64, capacity: None };
223 }
224 )*}; }
225 sequence!(Vec, VecDeque, BTreeSet);
226 impl<K: ValueDecode, V: ValueDecode> ValueDecode for BTreeMap<K, V> {
227 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Map {
228 key: ValueDecodeRef::of::<K>(),
229 value: ValueDecodeRef::of::<V>(),
230 };
231 }
232 macro_rules! delegate { ($($container:ident),*) => {$(
233 impl<T: ValueDecode> ValueDecode for $container<T> { const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Delegate(ValueDecodeRef::of::<T>()); }
234 )*}; }
235 delegate!(Box, Rc, Arc);
236}
237
238macro_rules! tuple_len { ($($ty:ident),+) => { [$(stringify!($ty)),+].len() }; }
239
240macro_rules! tuples {
241 ($($ty:ident:$index:tt),+) => {
242 impl<$($ty: ValueDecode),+> ValueDecode for ($($ty,)+) {
243 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Record { shape: RecordShape::Tuple, fields: { const LEN: usize = tuple_len!($($ty),+); &[$(
244 ValueDecodeField { selector: FieldSelector::Index { index: $index, declared_fields: LEN }, declaration_index: $index, value: ValueDecodeRef::of::<$ty>() }
245 ),+] } };
246 }
247 };
248}
249tuples!(A:0);
250tuples!(A:0,B:1);
251tuples!(A:0,B:1,C:2);
252tuples!(A:0,B:1,C:2,D:3);
253tuples!(A:0,B:1,C:2,D:3,E:4);
254tuples!(A:0,B:1,C:2,D:3,E:4,F:5);
255tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6);
256tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7);
257tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8);
258tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9);
259tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10);
260tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10,L:11);
261
262#[cfg(feature = "std")]
263mod standard {
264 use super::*;
265 use std::collections::{HashMap, HashSet};
266 impl<K: ValueDecode, V: ValueDecode, S: 'static> ValueDecode for HashMap<K, V, S> {
267 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Map {
268 key: ValueDecodeRef::of::<K>(),
269 value: ValueDecodeRef::of::<V>(),
270 };
271 }
272 impl<T: ValueDecode, S: 'static> ValueDecode for HashSet<T, S> {
273 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence {
274 element: ValueDecodeRef::of::<T>(),
275 count: Scalar::U64,
276 capacity: None,
277 };
278 }
279}
280
281macro_rules! encode_description_kind {
283 ($ty:ident, {$($variant:ident = $id:literal,)+}) => {
284 impl crate::Encode for $ty {
285 fn encode<E: crate::enc::Encoder>(&self, encoder: &mut E) -> Result<(), crate::error::EncodeError> {
286 (*self as u32).encode(encoder)
287 }
288 }
289 impl<Context> crate::Decode<Context> for $ty {
290 fn decode<D: crate::de::Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, crate::error::DecodeError> {
291 match <u32 as crate::Decode<Context>>::decode(decoder)? {
292 $($id => Ok(Self::$variant),)+
293 found => Err(crate::error::DecodeError::UnexpectedVariant {
294 type_name: core::any::type_name::<Self>(),
295 allowed: &crate::error::AllowedEnumVariants::Allowed(&[$($id,)+]),
296 found,
297 }),
298 }
299 }
300 }
301 crate::impl_borrow_decode!($ty);
302 impl ValueDecode for $ty {
303 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Enum {
304 tag: Scalar::U32,
305 variants: &[$(ValueDecodeVariant {
306 tag: $id,
307 name: stringify!($variant),
308 shape: RecordShape::Unit,
309 fields: &[],
310 },)+],
311 };
312 }
313 };
314}
315encode_description_kind!(Scalar, {
316 Bool = 0,
317 U8 = 1,
318 U16 = 2,
319 U32 = 3,
320 U64 = 4,
321 U128 = 5,
322 I8 = 6,
323 I16 = 7,
324 I32 = 8,
325 I64 = 9,
326 I128 = 10,
327 F32 = 11,
328 F64 = 12,
329 Char = 13,
330});
331encode_description_kind!(RecordShape, {
332 Unit = 0,
333 Tuple = 1,
334 Newtype = 2,
335 Struct = 3,
336});
337
338impl crate::Encode for ValueMetadata {
339 fn encode<E: crate::enc::Encoder>(
340 &self,
341 encoder: &mut E,
342 ) -> Result<(), crate::error::EncodeError> {
343 self.kind_id().encode(encoder)?;
344 match *self {
345 ValueMetadata::Quantity(quantity) => {
346 let mut bytes = [0; 8];
347 bytes[..4].copy_from_slice(&quantity.quantity().id().to_le_bytes());
348 bytes[4..].copy_from_slice(&quantity.storage_unit().id().to_le_bytes());
349 bytes.as_slice().encode(encoder)
350 }
351 }
352 }
353}