wasefire_wire/
internal.rs1pub use alloc::vec::Vec;
18
19use wasefire_error::{Code, Error, Space};
20
21#[cfg(feature = "schema")]
22pub use self::schema::*;
23pub use crate::reader::Reader;
24pub use crate::writer::Writer;
25
26pub type Result<T> = core::result::Result<T, Error>;
27
28pub trait Wire<'a>: 'a + Sized {
29 type Type<'b>: 'b + Sized + Wire<'b>; #[cfg(feature = "schema")]
31 fn schema(rules: &mut Rules);
32 fn encode(&self, writer: &mut Writer<'a>) -> Result<()>;
33 fn decode(reader: &mut Reader<'a>) -> Result<Self>;
34}
35
36pub const INVALID_TAG: Error = Error::new_const(Space::User as u8, Code::InvalidArgument as u16);
37
38pub fn encode_tag(tag: u32, writer: &mut Writer) -> Result<()> {
39 <u32 as crate::internal::Wire>::encode(&tag, writer)
40}
41
42pub fn decode_tag(reader: &mut Reader) -> Result<u32> {
43 <u32 as crate::internal::Wire>::decode(reader)
44}
45
46#[cfg(feature = "schema")]
47mod schema {
48 use alloc::vec::Vec;
49 use core::any::TypeId;
50 use std::collections::HashMap;
51 use std::collections::hash_map::Entry;
52
53 use crate::Wire;
54
55 pub fn schema<'a, T: Wire<'a>>(rules: &mut Rules) {
56 T::schema(rules)
57 }
58
59 pub fn type_id<'a, T: Wire<'a>>() -> TypeId {
60 TypeId::of::<T::Type<'static>>()
61 }
62
63 #[derive(Debug, Copy, Clone, PartialEq, Eq, wasefire_wire_derive::Wire)]
64 #[wire(crate = crate, range = 11)]
65 pub enum Builtin {
66 Bool,
67 U8,
68 I8,
69 U16,
70 I16,
71 U32,
72 I32,
73 U64,
74 I64,
75 Usize,
76 Isize,
77 }
78
79 #[derive(Debug, Default)]
80 pub struct Rules(HashMap<TypeId, Rule>);
81
82 #[derive(Debug, Clone, PartialEq, Eq)]
83 pub enum Rule {
84 Builtin(Builtin),
85 Alias(TypeId),
86 Array(TypeId, usize),
87 Slice(TypeId),
88 Struct(RuleStruct),
89 Enum(RuleEnum),
90 }
91 pub type RuleStruct = Vec<(Option<&'static str>, TypeId)>;
92 pub type RuleEnum = Vec<(&'static str, u32, RuleStruct)>;
93
94 impl Rules {
95 pub(crate) fn builtin<X: 'static>(&mut self, builtin: Builtin) {
96 let _ = self.insert::<X>(Rule::Builtin(builtin));
97 }
98
99 pub fn alias<X: 'static, T: Wire<'static>>(&mut self) {
100 if self.insert::<X>(Rule::Alias(TypeId::of::<T>())) {
101 T::schema(self);
102 }
103 }
104
105 pub(crate) fn array<X: 'static, T: Wire<'static>>(&mut self, n: usize) {
106 if self.insert::<X>(Rule::Array(TypeId::of::<T>(), n)) {
107 T::schema(self);
108 }
109 }
110
111 pub(crate) fn slice<X: 'static, T: Wire<'static>>(&mut self) {
112 if self.insert::<X>(Rule::Slice(TypeId::of::<T>())) {
113 T::schema(self);
114 }
115 }
116
117 pub fn struct_<X: 'static>(&mut self, fields: RuleStruct) -> bool {
118 self.insert::<X>(Rule::Struct(fields))
119 }
120
121 pub fn enum_<X: 'static>(&mut self, variants: RuleEnum) -> bool {
122 self.insert::<X>(Rule::Enum(variants))
123 }
124
125 fn insert<T: 'static>(&mut self, rule: Rule) -> bool {
126 match self.0.entry(TypeId::of::<T>()) {
127 Entry::Occupied(old) => {
128 assert_eq!(old.get(), &rule);
129 false
130 }
131 Entry::Vacant(x) => {
132 let _ = x.insert(rule);
133 true
134 }
135 }
136 }
137
138 pub(crate) fn get(&self, mut id: TypeId) -> &Rule {
139 for _ in 0 .. 40 {
140 match self.0.get(&id).unwrap() {
141 Rule::Alias(x) => id = *x,
142 x => return x,
143 }
144 }
145 panic!("possible alias cycle in schema rules");
146 }
147 }
148}