1use serde::{Serialize, de::DeserializeOwned};
2
3#[derive(Clone, Copy, Debug)]
5pub struct Shape {
6 pub bytes: usize,
8 pub heap: usize,
10 pub nodes: usize,
12 pub depth: usize,
14}
15impl Shape {
16 pub const fn scalar(bytes: usize) -> Self {
18 Self {
19 bytes,
20 heap: 0,
21 nodes: 1,
22 depth: 1,
23 }
24 }
25 pub const fn record(children: &[Self]) -> Self {
27 let mut out = Self::scalar(0);
28 let mut i = 0;
29 while i < children.len() {
30 let child = children[i];
31 out.bytes = out.bytes.saturating_add(child.bytes);
32 out.heap = out.heap.saturating_add(child.heap);
33 out.nodes = out.nodes.saturating_add(child.nodes);
34 let depth = child.depth.saturating_add(1);
35 if depth > out.depth {
36 out.depth = depth;
37 }
38 i += 1;
39 }
40 out
41 }
42 pub const fn choice(tag_bytes: usize, alternatives: &[Self]) -> Self {
44 let mut out = Self::scalar(0);
45 let mut i = 0;
46 while i < alternatives.len() {
47 let child = alternatives[i];
48 if child.bytes > out.bytes {
49 out.bytes = child.bytes;
50 }
51 if child.heap > out.heap {
52 out.heap = child.heap;
53 }
54 if child.nodes > out.nodes {
55 out.nodes = child.nodes;
56 }
57 if child.depth > out.depth {
58 out.depth = child.depth;
59 }
60 i += 1;
61 }
62 out.bytes = out.bytes.saturating_add(tag_bytes);
63 out.nodes = out.nodes.saturating_add(1);
64 out.depth = out.depth.saturating_add(1);
65 out
66 }
67}
68
69pub trait Wire: Serialize + DeserializeOwned {
75 const SHAPE: Shape;
77 const SCHEMA: crate::schema::Schema = crate::schema::Schema::Opaque;
79}
80
81#[derive(Clone, Copy, Debug)]
83pub struct Limits {
84 pub bytes: usize,
86 pub allocation: usize,
88 pub nodes: usize,
90 pub depth: usize,
92}
93macro_rules! scalars {
94 ($($ty:ty => ($bytes:expr, $schema:expr)),* $(,)?) => { $(
95 impl Wire for $ty {
96 const SHAPE: Shape = Shape::scalar($bytes);
97 const SCHEMA: crate::schema::Schema = $schema;
98 }
99 )* };
100}
101use crate::schema::Schema;
102scalars! { () => (0, Schema::Unit), bool => (1, Schema::Bool),
103u8 => (1, Schema::Unsigned(8)), i8 => (1, Schema::Signed(8)),
104u16 => (3, Schema::Unsigned(16)), i16 => (3, Schema::Signed(16)),
105u32 => (5, Schema::Unsigned(32)), i32 => (5, Schema::Signed(32)),
106u64 => (10, Schema::Unsigned(64)), i64 => (10, Schema::Signed(64)),
107u128 => (19, Schema::Unsigned(128)), i128 => (19, Schema::Signed(128)) }
108impl<T: Wire> Wire for Option<T> {
109 const SHAPE: Shape = Shape::choice(1, &[T::SHAPE]);
110 const SCHEMA: Schema = Schema::Option(&T::SCHEMA);
111}
112impl<T: Wire, E: Wire> Wire for Result<T, E> {
113 const SHAPE: Shape = Shape::choice(1, &[T::SHAPE, E::SHAPE]);
114 const SCHEMA: Schema = Schema::Result(&T::SCHEMA, &E::SCHEMA);
115}
116
117impl<T: Wire, const N: usize> Wire for [T; N]
118where
119 [T; N]: Serialize + DeserializeOwned,
120{
121 const SCHEMA: Schema = Schema::Array(&T::SCHEMA, N);
122 const SHAPE: Shape = Shape {
123 bytes: T::SHAPE.bytes.saturating_mul(N),
124 heap: T::SHAPE.heap.saturating_mul(N),
125 nodes: 1_usize.saturating_add(T::SHAPE.nodes.saturating_mul(N)),
126 depth: T::SHAPE.depth.saturating_add(1),
127 };
128}