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