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, 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        // let (a, k) = opt(tag("n"))(a)?;
161        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    // #[display(fmt = "{}", _0)]
197    // Func(Sig),
198}
199pub fn parse_arg(a: &str) -> IResult<&str, Arg> {
200    let (a, ann) = parse_attrs(a)?;
201    let (a, _) = multispace0(a)?;
202    // let (c,b) = take(1usize)(a)?;
203    match a.strip_prefix("R") {
204        Some(b) => {
205            // if let Some(a) = b.strip_prefix("this"){
206            //     let (a, k) = opt(tag("n"))(a)?;
207            //     return Ok((
208            //         a,
209            //         Arg::Resource {
210            //             ty: ResTy::This,
211            //             nullable: k.is_some(),
212            //         },
213            //     ));
214            // }
215            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        // "(" => {
229        //     let (a, x) = parse_sig(a)?;
230        //     return Ok((a, Arg::Func(x)));
231        // }
232        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::io::Write;
319        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}