1#![no_std]
2extern crate alloc;
3use alloc::{
4 borrow::ToOwned,
5 collections::BTreeMap,
6 format,
7 string::{String, ToString},
8 vec,
9 vec::Vec,
10};
11use core::convert::identity as tuple;
12use core::fmt::{self, Display};
13use derive_more::Display;
14use nom::{
15 bytes::complete::{is_not, tag, take, take_while_m_n},
16 character::complete::{alpha1, alphanumeric1, char, multispace0},
17 combinator::opt,
18 error::Error,
19 multi::{many0, separated_list0},
20 sequence::delimited,
21 IResult, Parser,
22};
23use sha3::{Digest, Sha3_256};
24#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
25pub struct Attr {
26 pub name: String,
27 pub value: String,
28}
29
30impl Attr {
31 pub fn as_wasm_abi(&self) -> Option<usize> {
32 if self.name == "wasmAbiVer" {
33 Some(usize::from_str_radix(&self.value, 16).ok()? + 1)
34 } else {
35 None
36 }
37 }
38 pub fn from_wasm_abi(ver: usize) -> Option<Self> {
39 if ver == 0 {
40 None
41 } else {
42 let ver = ver - 1;
43 Some(Self {
44 name: "wasmAbiVer".to_owned(),
45 value: format!("{ver:x}"),
46 })
47 }
48 }
49}
50
51pub fn merge(a: Vec<Attr>, b: Vec<Attr>) -> Vec<Attr> {
52 let mut m = BTreeMap::new();
53 for x in a.into_iter().chain(b) {
54 m.insert(x.name, x.value);
55 }
56 return m
57 .into_iter()
58 .map(|(a, b)| Attr { name: a, value: b })
59 .collect();
60}
61
62pub fn parse_balanced(mut a: &str) -> IResult<&str, String> {
63 let mut v = Vec::default();
64 let mut i = 0;
65 loop {
66 let (b, x) = nom::character::complete::anychar(a)?;
67 match x {
68 '[' => i += 1,
69 ']' => {
70 if i == 0 {
71 return Ok((a, v.into_iter().collect()));
72 }
73 i -= 1;
74 }
75 _ => {}
76 }
77 a = b;
78 v.push(x)
79 }
80}
81
82pub fn parse_attr(a: &str) -> IResult<&str, Attr> {
83 let (a, _) = multispace0(a)?;
84 let (a, _) = char('[')(a)?;
85 let (a, _) = multispace0(a)?;
86 let (a, name) = alphanumeric1(a)?;
87 let (a, _) = multispace0(a)?;
88 let (a, _) = char('=')(a)?;
89 let (a, _) = multispace0(a)?;
90 let (a, value) = parse_balanced(a)?;
91 let (a, _) = char(']')(a)?;
92 let (a, _) = multispace0(a)?;
93 return Ok((
94 a,
95 Attr {
96 name: name.to_owned(),
97 value,
98 },
99 ));
100}
101
102pub fn parse_attrs(a: &str) -> IResult<&str, Vec<Attr>> {
103 let (a, mut b) = many0(parse_attr).parse(a)?;
104 b.sort_by_key(|a| a.name.clone());
105 Ok((a, b))
106}
107
108impl Display for Attr {
109 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
110 write!(f, "[{}={}]", self.name, self.value)
111 }
112}
113#[non_exhaustive]
114#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
115pub enum ResTy {
116 #[display("")]
117 None,
118 #[display("{}", hex::encode(_0))]
119 Of([u8; 32]),
120 #[display("this")]
121 This,
122}
123pub fn parse_resty(a: &str) -> IResult<&str, ResTy> {
124 if let Some(a) = a.strip_prefix("this") {
125 return Ok((a, ResTy::This));
127 }
128 let (a, d) = opt(take_while_m_n(64, 64, |a: char| a.is_digit(16))).parse(a)?;
129 return Ok((
130 a,
131 match d {
132 Some(d) => {
133 let mut b = [0u8; 32];
134 hex::decode_to_slice(d, &mut b).unwrap();
135 ResTy::Of(b)
136 }
137 None => ResTy::None,
138 },
139 ));
140}
141#[non_exhaustive]
142#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
143pub enum Arg {
144 I32,
145 I64,
146 F32,
147 F64,
148 #[display(
149 "{}R{}{}{}",
150 ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(""),
151 ty,
152 if *nullable{"n"}else{""},
153 if *take{""}else{"&"}
154 )]
155 Resource {
156 ty: ResTy,
157 nullable: bool,
158 take: bool,
159 ann: Vec<Attr>,
160 },
161 }
164pub fn parse_arg(a: &str) -> IResult<&str, Arg> {
165 let (a, ann) = parse_attrs(a)?;
166 let (a, _) = multispace0(a)?;
167 match a.strip_prefix("R") {
169 Some(b) => {
170 let (a, d) = parse_resty(b)?;
181 let (a, k) = opt(tag("n")).parse(a)?;
182 let (a, take) = opt(tag("&")).parse(a)?;
183 return Ok((
184 a,
185 Arg::Resource {
186 ty: d,
187 nullable: k.is_some(),
188 take: take.is_none(),
189 ann,
190 },
191 ));
192 }
193 None => {
198 let (a, c) = take(3usize)(a)?;
199 match c {
200 "I32" => return Ok((a, Arg::I32)),
201 "I64" => return Ok((a, Arg::I64)),
202 "F32" => return Ok((a, Arg::F32)),
203 "F64" => return Ok((a, Arg::F64)),
204 _ => return Err(nom::Err::Error(Error::new(a, nom::error::ErrorKind::Tag))),
205 }
206 }
207 }
208 todo!()
209}
210#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
211#[display(
212 "{}({}) -> ({})",
213 ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(""),
214 params.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(","),
215 rets.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(",")
216)]
217pub struct Sig {
218 pub ann: Vec<Attr>,
219 pub params: Vec<Arg>,
220 pub rets: Vec<Arg>,
221}
222pub fn parse_sig(a: &str) -> IResult<&str, Sig> {
223 let (a, b) = parse_attrs(a)?;
224 let (a, _) = multispace0(a)?;
225 let mut d = delimited(char('('), separated_list0(char(','), parse_arg), char(')'));
226 let (a, params) = d.parse(a)?;
227 let (a, _) = multispace0(a)?;
228 let (a, _) = tag("->")(a)?;
229 let (a, _) = multispace0(a)?;
230 let (a, rets) = d.parse(a)?;
231 return Ok((
232 a,
233 Sig {
234 params,
235 rets,
236 ann: b,
237 },
238 ));
239}
240#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
241pub struct Interface {
242 pub methods: BTreeMap<String, Sig>,
243 pub ann: Vec<Attr>,
244}
245impl Display for Interface {
246 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
247 for a in self.ann.iter() {
248 write!(f, "{a}")?;
249 }
250 write!(f, "{}", "{")?;
251 let mut x = self.methods.iter().collect::<Vec<_>>();
252 x.sort_by_key(|a| a.0);
253 for (i, (a, b)) in x.into_iter().enumerate() {
254 if i != 0 {
255 write!(f, ";")?;
256 }
257 write!(f, "{}{}", a, b)?;
258 }
259 return write!(f, "{}", "}");
260 }
261}
262pub fn parse_interface(a: &str) -> IResult<&str, Interface> {
263 pub fn go(a: &str) -> IResult<&str, Interface> {
264 let (a, s) =
265 separated_list0(char(';'), tuple((multispace0, alphanumeric1, parse_sig))).parse(a)?;
266 let (a, _) = multispace0(a)?;
267 return Ok((
268 a,
269 Interface {
270 methods: s.into_iter().map(|(_, a, b)| (a.to_owned(), b)).collect(),
271 ann: vec![],
272 },
273 ));
274 }
275 let (a, _) = multispace0(a)?;
276 let (a, b) = parse_attrs(a)?;
277 let (a, mut c) = delimited(char('{'), go, char('}')).parse(a)?;
278 c.ann = b;
279 return Ok((a, c));
280}
281impl Interface {
282 pub fn rid(&self) -> [u8; 32] {
283 use core::fmt::Write;
285 let mut s = Sha3_256::default();
286 s.update(self.to_string());
287 return s.finalize().try_into().unwrap();
288 }
289 pub fn rid_str(&self) -> String {
290 return hex::encode(self.rid());
291 }
292}
293pub mod info;
294pub fn retuple(a: Vec<Arg>) -> Interface {
295 Interface {
296 methods: a
297 .into_iter()
298 .enumerate()
299 .map(|(a, b)| {
300 (
301 format!("v{a}"),
302 Sig {
303 ann: vec![],
304 params: vec![],
305 rets: vec![b],
306 },
307 )
308 })
309 .collect(),
310 ann: vec![],
311 }
312}