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