1use std::{collections::BTreeMap, fmt::Display};
2
3use nom::{
4 bytes::complete::{tag, take_while_m_n}, character::complete::{alphanumeric1, multispace0}, multi::many0, sequence::delimited, IResult
5};
6
7use crate::{merge, parse_attr, Attr};
8#[derive(Default,Clone)]
9pub struct Info {
10 pub interfaces: BTreeMap<[u8; 32], InfoEntry>,
11}
12impl Info{
13 pub fn merge(self, x: Info) -> Info{
14 let mut m: BTreeMap<[u8;32],InfoEntry> = BTreeMap::new();
15 for (a,b) in self.interfaces.into_iter().chain(x.interfaces.into_iter()){
16 let c = m.remove(&a).unwrap_or_default().merge(b);
17 m.insert(a, c);
18 }
19 Info { interfaces: m }
20 }
21}
22#[derive(Default,Clone)]
23pub struct InfoEntry {
24 pub attrs: Vec<Attr>,
25 pub methods: BTreeMap<String,MethEntry>
26}
27impl InfoEntry{
28 pub fn merge(self, x: InfoEntry) -> InfoEntry{
29 let mut m: BTreeMap<String, MethEntry> = BTreeMap::new();
30 for (a,b) in self.methods.into_iter().chain(x.methods.into_iter()){
31 let c = m.remove(&a).unwrap_or_default().merge(b);
32 m.insert(a, c);
33 }
34 InfoEntry { attrs: merge(self.attrs, x.attrs), methods: m }
35 }
36}
37#[derive(Default,Clone)]
38pub struct MethEntry{
39 pub attrs: Vec<Attr>
40}
41impl MethEntry{
42 pub fn merge(self, x: MethEntry) -> MethEntry{
43 MethEntry { attrs: merge(self.attrs, x.attrs) }
44 }
45}
46impl Display for InfoEntry {
47 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
48 for a in self.attrs.iter(){
49 write!(f,"root {a}")?;
50 }
51 for (k,m) in self.methods.iter(){
52 for a in m.attrs.iter(){
53 write!(f,"method {k} {a}")?;
54 }
55 }
56 Ok(())
57 }
58}
59impl Display for Info {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 for (i, j) in self.interfaces.iter() {
62 write!(f, "{}: [{j}]", hex::encode(i))?;
63 }
64 Ok(())
65 }
66}
67pub fn parse_entry(a: &str) -> IResult<&str, InfoEntry> {
68 let (a,_) = multispace0(a)?;
69 pub fn go1(a: &str) -> IResult<&str,Attr>{
70 let (a,_) = multispace0(a)?;
71 let (a,_) = tag("root")(a)?;
72 let (a,_) = multispace0(a)?;
73 return parse_attr(a);
74 }
75 pub fn go2(a: &str) -> IResult<&str,(&str,Attr)>{
76 let (a,_) = multispace0(a)?;
77 let (a,_) = tag("method")(a)?;
78 let (a,_) = multispace0(a)?;
79 let (a,b) = alphanumeric1(a)?;
80 let (a,_) = multispace0(a)?;
81 let (a,c) = parse_attr(a)?;
82 Ok((a,(b,c)))
83 }
84 let (a,mut e) = many0(go1)(a)?;
85 e.sort_by_key(|k|k.name.clone());
86 let mut n: BTreeMap<String, MethEntry> = BTreeMap::new();
87 let (a,l) = many0(go2)(a)?;
88 for (k,v) in l{
89 n.entry(k.to_owned()).or_insert_with(Default::default).attrs.push(v);
90 }
91 for v in n.values_mut(){
92 v.attrs.sort_by_key(|k|k.name.clone());
93 }
94 let (a,_) = multispace0(a)?;
95 Ok((a, InfoEntry { attrs: e, methods: n }))
96}
97pub fn parse_info(a: &str) -> IResult<&str, Info> {
98 pub fn go(a: &str) -> IResult<&str, ([u8; 32], InfoEntry)> {
99 let (a,_) = multispace0(a)?;
100 let (a, d) = take_while_m_n(64, 64, |a: char| a.is_digit(16))(a)?;
101 let mut b = [0u8; 32];
102 hex::decode_to_slice(d, &mut b).unwrap();
103 let (a,_) = multispace0(a)?;
104 let (a,_) = tag(":")(a)?;
105 let (a,_) = multispace0(a)?;
106 let (a, c) = delimited(tag("["), parse_entry, tag("]"))(a)?;
107 return Ok((a, (b, c)));
108 }
109 let (a, all) = many0(go)(a)?;
110 Ok((
111 a,
112 Info {
113 interfaces: all.into_iter().collect(),
114 },
115 ))
116}