1use super::{Parser, Result};
4use crate::{parser::combinators::Map, Die, DwarfDb};
5
6pub struct ParseChildren<T> {
8 parsers: T,
9}
10
11pub fn parse_children<T>(parsers: T) -> ParseChildren<T> {
13 ParseChildren { parsers }
14}
15
16fn extract_tuple<T>(tuple: (T,)) -> T {
17 tuple.0
18}
19
20type ExtractTuple<T> = fn((T,)) -> T;
21
22pub fn child<P, T>(parser: P) -> Map<ParseChildren<(P,)>, ExtractTuple<T>, (T,)>
24where
25 P: Parser<T>,
26{
27 Map {
28 parser: parse_children((parser,)),
29 f: extract_tuple,
30 _marker: std::marker::PhantomData,
31 }
32}
33
34pub struct ForEachChild<P> {
36 parser: P,
37}
38
39pub fn for_each_child<P>(parser: P) -> ForEachChild<P> {
40 ForEachChild { parser }
41}
42
43impl<T, P> Parser<Vec<T>> for ForEachChild<P>
44where
45 P: Parser<T>,
46{
47 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<Vec<T>> {
48 let mut results = Vec::new();
49
50 for child in entry.children(db)? {
51 match self.parser.parse(db, child) {
52 Ok(result) => {
53 results.push(result);
54 }
55 Err(e) => {
56 tracing::trace!(
57 "Failed to parse child: {}: {}",
58 child.format_with_location(db, child.print(db)),
59 e
60 );
61 continue;
66 }
67 }
68 }
70
71 Ok(results)
72 }
73}
74pub struct TryForEachChild<P> {
75 parser: P,
76}
77
78pub fn try_for_each_child<P>(parser: P) -> TryForEachChild<P> {
79 TryForEachChild { parser }
80}
81
82impl<T, P> Parser<Vec<T>> for TryForEachChild<P>
83where
84 P: Parser<Option<T>>,
85{
86 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<Vec<T>> {
87 let mut results = Vec::new();
88
89 for child in entry.children(db)? {
90 if let Some(result) = self.parser.parse(db, child)? {
91 results.push(result);
92 }
93 }
95
96 Ok(results)
97 }
98}
99
100macro_rules! impl_parse_children_for_tuples {
102 (
103 $($P:ident, $T:ident, $idx:tt),*
104 ) => {
105 impl< $($T, $P,)*> Parser< ($($T,)*)> for ParseChildren<($($P,)*)>
106 where
107 $($P: Parser< $T>),*
108 {
109 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> anyhow::Result<($($T,)*)> {
110
111 #[allow(unused)] let mut result = ($(
113 None::<anyhow::Result<$T>>,
114 )*);
115
116 for child in entry.children(db)? {
117 tracing::trace!(
118 "Parsing child: {}",
119 child.format_with_location(db, child.print(db))
120 );
121
122 $(
123 if result.$idx.is_none() {
124 match self.parsers.$idx.parse(db, child) {
125 Ok(res) => {
126 result.$idx = Some(Ok(res));
127 }
128 Err(_) => {}
129 }
130 }
131 )*
132 }
133
134 let result = ($(
135 result.$idx.ok_or_else(|| anyhow::anyhow!("Failed to find required child for parser at index {}", $idx))??,
136 )*);
137 Ok(result)
138 }
139 }
140 };
141}
142
143impl_parse_children_for_tuples!();
145impl_parse_children_for_tuples!(P0, T0, 0);
146impl_parse_children_for_tuples!(P0, T0, 0, P1, T1, 1);
147impl_parse_children_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2);
148impl_parse_children_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3);
149impl_parse_children_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4);
150impl_parse_children_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5);
151impl_parse_children_for_tuples!(
152 P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5, P6, T6, 6
153);
154impl_parse_children_for_tuples!(
155 P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5, P6, T6, 6, P7, T7, 7
156);