1use postcard_schema_ng::{
4 Schema,
5 key::{
6 Key,
7 hash::{HashItem, HashOptions, fnv1a64::hasher},
8 },
9 schema::DataModelType,
10};
11use serde::{Deserialize, Serialize};
12
13const fn method_hasher<T: Schema, U: Schema>(path: &str) -> Key {
14 let mut options = HashOptions::DEFAULT;
15 options.hash_max_size = true;
16 let items = [
17 HashItem::String(path),
18 HashItem::Schema(T::SCHEMA),
19 HashItem::Schema(U::SCHEMA),
20 ];
21 Key::from_bytes(hasher(&options, &items))
22}
23
24pub trait Method {
26 type Request<'rqst>: Schema + Serialize + Deserialize<'rqst>;
27 type Response<'resp>: Schema + Serialize + Deserialize<'resp>;
28
29 const NAME: &'static str;
30
31 const KEY: Key = method_hasher::<Self::Request<'static>, Self::Response<'static>>(Self::NAME);
32
33 const INFO: MethodInfo = MethodInfo {
34 name: Self::NAME,
35 key: Self::KEY,
36 req_schema: <Self::Request<'static> as Schema>::SCHEMA,
37 resp_schema: <Self::Response<'static> as Schema>::SCHEMA,
38 };
39}
40
41#[derive(Debug, Clone, Copy)]
43pub struct MethodInfo {
44 pub name: &'static str,
45 pub key: Key,
46 pub req_schema: &'static DataModelType,
47 pub resp_schema: &'static DataModelType,
48}
49
50#[derive(Debug, Clone, Copy)]
52pub struct InterfaceInfo {
53 pub max_request_size: Option<usize>,
54 pub max_response_size: Option<usize>,
55 pub methods: &'static [MethodInfo],
56}
57
58pub const fn rqst_body_max_buf_required(infos: &[MethodInfo]) -> Option<usize> {
62 let mut max = crate::wire::WireError::SCHEMA.max_size().unwrap();
64 let mut idx = 0;
65 while idx < infos.len() {
66 let Some(m) = infos[idx].req_schema.max_size() else {
67 return None;
68 };
69 if m > max {
70 max = m;
71 }
72 idx += 1;
73 }
74 Some(max)
75}
76
77pub const fn resp_body_max_buf_required(infos: &[MethodInfo]) -> Option<usize> {
81 let mut max = crate::wire::WireError::SCHEMA.max_size().unwrap();
83 let mut idx = 0;
84 while idx < infos.len() {
85 let Some(m) = infos[idx].resp_schema.max_size() else {
86 return None;
87 };
88 if m > max {
89 max = m;
90 }
91 idx += 1;
92 }
93 Some(max)
94}
95
96pub const fn total_len(sets: &[&[MethodInfo]]) -> usize {
99 let mut i = 0;
100 let mut ct = 0;
101 while i < sets.len() {
102 ct += sets[i].len();
103 i += 1;
104 }
105 ct
106}
107
108pub const fn flatten<const N: usize>(sets: &[&[MethodInfo]]) -> [MethodInfo; N] {
112 pub const ONE: MethodInfo = MethodInfo {
113 name: "",
114 key: Key::from_bytes([0; 8]),
115 req_schema: &DataModelType::Unit,
116 resp_schema: &DataModelType::Unit,
117 };
118
119 let mut out = [ONE; N];
120 let mut i = 0;
121 let mut n = 0;
122 while i < sets.len() {
123 let mut k = 0;
124 while k < sets[i].len() {
125 out[n] = sets[i][k];
126 k += 1;
127 n += 1;
128 }
129 i += 1;
130 }
131 assert!(n == N);
132 out
133}
134
135pub const fn extract_keys<const N: usize>(infos: &[MethodInfo]) -> [Key; N] {
139 assert!(N == infos.len());
140 let mut buf = [Key::from_bytes([0u8; 8]); N];
141 let mut idx = 0;
142 while idx < N {
143 buf[idx] = infos[idx].key;
144 idx += 1;
145 }
146 buf
147}