1use core::any::{TypeId, type_name};
6
7pub trait ValueDecode: 'static + Sized {
19 const DECODE: &'static ValueDecodeSpec;
21
22 #[doc(hidden)]
24 const __DECODE_REF: ValueDecodeRef = ValueDecodeRef {
25 describe: describe::<Self>,
26 };
27}
28
29#[derive(Clone, Copy, Debug)]
31pub struct ValueDecodeRef {
32 pub describe: fn() -> ValueDecodeType,
34}
35
36impl ValueDecodeRef {
37 pub const fn of<T: ValueDecode>() -> Self {
39 Self {
40 describe: describe::<T>,
41 }
42 }
43}
44
45fn describe<T: ValueDecode>() -> ValueDecodeType {
46 ValueDecodeType {
47 type_id: TypeId::of::<T>(),
48 type_name: type_name::<T>(),
49 spec: T::DECODE,
50 }
51}
52
53#[derive(Clone, Copy, Debug)]
55pub struct ValueDecodeType {
56 pub type_id: TypeId,
58 pub type_name: &'static str,
60 pub spec: &'static ValueDecodeSpec,
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
66pub enum Scalar {
67 Bool,
69 U8,
71 U16,
73 U32,
75 U64,
77 U128,
79 I8,
81 I16,
83 I32,
85 I64,
87 I128,
89 F32,
91 F64,
93 Char,
95}
96
97#[derive(Clone, Copy, Debug)]
99pub enum FieldSelector {
100 Named(&'static str),
102 Index {
104 index: usize,
106 declared_fields: usize,
108 },
109}
110
111#[derive(Clone, Copy, Debug)]
113pub struct ValueDecodeField {
114 pub selector: FieldSelector,
116 pub declaration_index: usize,
118 pub value: ValueDecodeRef,
120}
121
122#[derive(Clone, Copy, Debug)]
124pub enum RecordShape {
125 Unit,
127 Tuple,
129 Newtype,
131 Struct,
133}
134
135#[derive(Clone, Copy, Debug)]
137pub struct ValueDecodeVariant {
138 pub tag: u32,
140 pub name: &'static str,
142 pub shape: RecordShape,
144 pub fields: &'static [ValueDecodeField],
146}
147
148#[derive(Clone, Copy, Debug)]
150pub enum ValueDecodeSpec {
151 Unit,
153 Scalar(Scalar),
155 String,
157 Bytes,
159 Record {
161 shape: RecordShape,
163 fields: &'static [ValueDecodeField],
165 },
166 Array {
168 element: ValueDecodeRef,
170 len: usize,
172 },
173 Sequence {
175 element: ValueDecodeRef,
177 count: Scalar,
179 capacity: Option<usize>,
181 },
182 Map {
184 key: ValueDecodeRef,
186 value: ValueDecodeRef,
188 },
189 Option(ValueDecodeRef),
191 Delegate(ValueDecodeRef),
193 Enum {
195 tag: Scalar,
197 variants: &'static [ValueDecodeVariant],
199 },
200}
201
202macro_rules! scalars {
203 ($($ty:ty => $scalar:ident),* $(,)?) => {$(
204 impl ValueDecode for $ty { const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Scalar(Scalar::$scalar); }
205 )*};
206}
207scalars!(bool=>Bool, u8=>U8, u16=>U16, u32=>U32, u64=>U64, u128=>U128,
208 i8=>I8, i16=>I16, i32=>I32, i64=>I64, i128=>I128, f32=>F32, f64=>F64, char=>Char,
209 usize=>U64, isize=>I64);
210impl ValueDecode for () {
211 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Unit;
212}
213impl<T: 'static> ValueDecode for core::marker::PhantomData<T> {
214 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Unit;
215}
216impl<T: ValueDecode, const N: usize> ValueDecode for [T; N] {
217 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Array {
218 element: ValueDecodeRef::of::<T>(),
219 len: N,
220 };
221}
222impl<T: ValueDecode> ValueDecode for Option<T> {
223 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Option(ValueDecodeRef::of::<T>());
224}
225impl<T: ValueDecode> ValueDecode for &'static T {
226 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Delegate(ValueDecodeRef::of::<T>());
227}
228impl ValueDecode for &'static str {
229 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::String;
230}
231impl<T: ValueDecode> ValueDecode for &'static [T] {
232 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence {
233 element: ValueDecodeRef::of::<T>(),
234 count: Scalar::U64,
235 capacity: None,
236 };
237}
238
239#[cfg(feature = "alloc")]
240mod allocated {
241 use super::*;
242 use alloc::{
243 boxed::Box,
244 collections::{BTreeMap, BTreeSet, VecDeque},
245 rc::Rc,
246 string::String,
247 sync::Arc,
248 vec::Vec,
249 };
250 impl ValueDecode for String {
251 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::String;
252 }
253 macro_rules! sequence { ($($container:ident),*) => {$(
254 impl<T: ValueDecode> ValueDecode for $container<T> {
255 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence { element: ValueDecodeRef::of::<T>(), count: Scalar::U64, capacity: None };
256 }
257 )*}; }
258 sequence!(Vec, VecDeque, BTreeSet);
259 impl<K: ValueDecode, V: ValueDecode> ValueDecode for BTreeMap<K, V> {
260 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Map {
261 key: ValueDecodeRef::of::<K>(),
262 value: ValueDecodeRef::of::<V>(),
263 };
264 }
265 macro_rules! delegate { ($($container:ident),*) => {$(
266 impl<T: ValueDecode> ValueDecode for $container<T> { const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Delegate(ValueDecodeRef::of::<T>()); }
267 )*}; }
268 delegate!(Box, Rc, Arc);
269}
270
271macro_rules! tuple_len { ($($ty:ident),+) => { [$(stringify!($ty)),+].len() }; }
272
273macro_rules! tuples {
274 ($($ty:ident:$index:tt),+) => {
275 impl<$($ty: ValueDecode),+> ValueDecode for ($($ty,)+) {
276 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Record { shape: RecordShape::Tuple, fields: { const LEN: usize = tuple_len!($($ty),+); &[$(
277 ValueDecodeField { selector: FieldSelector::Index { index: $index, declared_fields: LEN }, declaration_index: $index, value: ValueDecodeRef::of::<$ty>() }
278 ),+] } };
279 }
280 };
281}
282tuples!(A:0);
283tuples!(A:0,B:1);
284tuples!(A:0,B:1,C:2);
285tuples!(A:0,B:1,C:2,D:3);
286tuples!(A:0,B:1,C:2,D:3,E:4);
287tuples!(A:0,B:1,C:2,D:3,E:4,F:5);
288tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6);
289tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7);
290tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8);
291tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9);
292tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10);
293tuples!(A:0,B:1,C:2,D:3,E:4,F:5,G:6,H:7,I:8,J:9,K:10,L:11);
294
295#[cfg(feature = "std")]
296mod standard {
297 use super::*;
298 use std::collections::{HashMap, HashSet};
299 impl<K: ValueDecode, V: ValueDecode, S: 'static> ValueDecode for HashMap<K, V, S> {
300 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Map {
301 key: ValueDecodeRef::of::<K>(),
302 value: ValueDecodeRef::of::<V>(),
303 };
304 }
305 impl<T: ValueDecode, S: 'static> ValueDecode for HashSet<T, S> {
306 const DECODE: &'static ValueDecodeSpec = &ValueDecodeSpec::Sequence {
307 element: ValueDecodeRef::of::<T>(),
308 count: Scalar::U64,
309 capacity: None,
310 };
311 }
312}