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