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