pit_core/
lib.rs

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        // let (a, k) = opt(tag("n"))(a)?;
126        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    // #[display(fmt = "{}", _0)]
162    // Func(Sig),
163}
164pub fn parse_arg(a: &str) -> IResult<&str, Arg> {
165    let (a, ann) = parse_attrs(a)?;
166    let (a, _) = multispace0(a)?;
167    // let (c,b) = take(1usize)(a)?;
168    match a.strip_prefix("R") {
169        Some(b) => {
170            // if let Some(a) = b.strip_prefix("this"){
171            //     let (a, k) = opt(tag("n"))(a)?;
172            //     return Ok((
173            //         a,
174            //         Arg::Resource {
175            //             ty: ResTy::This,
176            //             nullable: k.is_some(),
177            //         },
178            //     ));
179            // }
180            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        // "(" => {
194        //     let (a, x) = parse_sig(a)?;
195        //     return Ok((a, Arg::Func(x)));
196        // }
197        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::io::Write;
284        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}