1use alloc::boxed::Box;
2use serde::Serialize;
3
4#[derive(Clone, Copy, Debug)]
6pub struct Shape {
7 pub bytes: usize,
9 pub heap: usize,
11 pub nodes: usize,
13 pub depth: usize,
15}
16impl Shape {
17 pub const fn scalar(bytes: usize) -> Self {
19 Self {
20 bytes,
21 heap: 0,
22 nodes: 1,
23 depth: 1,
24 }
25 }
26 pub const fn record(children: &[Self]) -> Self {
28 let mut out = Self::scalar(0);
29 let mut i = 0;
30 while i < children.len() {
31 let child = children[i];
32 out.bytes = out.bytes.saturating_add(child.bytes);
33 out.heap = out.heap.saturating_add(child.heap);
34 out.nodes = out.nodes.saturating_add(child.nodes);
35 let depth = child.depth.saturating_add(1);
36 if depth > out.depth {
37 out.depth = depth;
38 }
39 i += 1;
40 }
41 out
42 }
43 pub const fn choice(tag_bytes: usize, alternatives: &[Self]) -> Self {
45 let mut out = Self::scalar(0);
46 let mut i = 0;
47 while i < alternatives.len() {
48 let child = alternatives[i];
49 if child.bytes > out.bytes {
50 out.bytes = child.bytes;
51 }
52 if child.heap > out.heap {
53 out.heap = child.heap;
54 }
55 if child.nodes > out.nodes {
56 out.nodes = child.nodes;
57 }
58 if child.depth > out.depth {
59 out.depth = child.depth;
60 }
61 i += 1;
62 }
63 out.bytes = out.bytes.saturating_add(tag_bytes);
64 out.nodes = out.nodes.saturating_add(1);
65 out.depth = out.depth.saturating_add(1);
66 out
67 }
68}
69
70pub trait Wire: Serialize {
78 #[doc(hidden)]
82 const __CANONICAL_FIELDS: bool = false;
83
84 #[doc(hidden)]
86 fn __canonical(
87 &self,
88 canonical: &mut crate::__private::Canonical<'_>,
89 ) -> Result<(), crate::Error> {
90 canonical.compare(self)
91 }
92
93 const SHAPE: Shape;
95 const SCHEMA: crate::schema::Schema = crate::schema::Schema::Opaque;
97}
98
99#[derive(Clone, Copy, Debug)]
101pub struct Limits {
102 pub bytes: usize,
104 pub allocation: usize,
106 pub nodes: usize,
108 pub depth: usize,
110}
111macro_rules! scalars {
112 ($($ty:ty => ($bytes:expr, $schema:expr)),* $(,)?) => { $(
113 impl Wire for $ty {
114 const __CANONICAL_FIELDS: bool = true;
115 const SHAPE: Shape = Shape::scalar($bytes);
116 const SCHEMA: crate::schema::Schema = $schema;
117 }
118 )* };
119}
120use crate::schema::Schema;
121scalars! { () => (0, Schema::Unit), bool => (1, Schema::Bool),
122u8 => (1, Schema::Unsigned(8)), i8 => (1, Schema::Signed(8)),
123u16 => (3, Schema::Unsigned(16)), i16 => (3, Schema::Signed(16)),
124u32 => (5, Schema::Unsigned(32)), i32 => (5, Schema::Signed(32)),
125u64 => (10, Schema::Unsigned(64)), i64 => (10, Schema::Signed(64)),
126u128 => (19, Schema::Unsigned(128)), i128 => (19, Schema::Signed(128)) }
127impl<T: Wire> Wire for Option<T> {
128 const __CANONICAL_FIELDS: bool = T::__CANONICAL_FIELDS;
129 const SHAPE: Shape = Shape::choice(1, &[T::SHAPE]);
130 const SCHEMA: Schema = Schema::Option(&T::SCHEMA);
131}
132impl<T: Wire, E: Wire> Wire for Result<T, E> {
133 const __CANONICAL_FIELDS: bool = T::__CANONICAL_FIELDS && E::__CANONICAL_FIELDS;
134 const SHAPE: Shape = Shape::choice(1, &[T::SHAPE, E::SHAPE]);
135 const SCHEMA: Schema = Schema::Result(&T::SCHEMA, &E::SCHEMA);
136}
137
138impl<T: Wire> Wire for Box<T> {
141 const __CANONICAL_FIELDS: bool = T::__CANONICAL_FIELDS;
142 const SHAPE: Shape = Shape {
143 heap: core::mem::size_of::<T>().saturating_add(T::SHAPE.heap),
144 ..T::SHAPE
145 };
146 const SCHEMA: Schema = T::SCHEMA;
147}
148
149impl<T: Wire, const N: usize> Wire for [T; N]
150where
151 [T; N]: Serialize,
152{
153 const __CANONICAL_FIELDS: bool = T::__CANONICAL_FIELDS;
154 const SCHEMA: Schema = Schema::Array(&T::SCHEMA, N);
155 const SHAPE: Shape = Shape {
156 bytes: T::SHAPE.bytes.saturating_mul(N),
157 heap: T::SHAPE.heap.saturating_mul(N),
158 nodes: 1_usize.saturating_add(T::SHAPE.nodes.saturating_mul(N)),
159 depth: T::SHAPE.depth.saturating_add(1),
160 };
161}