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