1use anyhow::Context as _;
4
5use super::{Parser, Result};
6use crate::{Die, DwarfDb};
7
8pub struct And<P1, P2, T, U> {
10 pub(super) first: P1,
11 pub(super) second: P2,
12 pub(super) _marker: std::marker::PhantomData<(T, U)>,
13}
14
15impl<T, U, P1, P2> Parser<(T, U)> for And<P1, P2, T, U>
16where
17 P1: Parser<T>,
18 P2: Parser<U>,
19{
20 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<(T, U)> {
21 let first_result = self.first.parse(db, entry)?;
22 let second_result = self.second.parse(db, entry)?;
23 Ok((first_result, second_result))
24 }
25}
26
27pub struct Map<P, F, T> {
29 pub(super) parser: P,
30 pub(super) f: F,
31 pub(super) _marker: std::marker::PhantomData<T>,
32}
33
34impl<T, U, P, F> Parser<U> for Map<P, F, T>
35where
36 P: Parser<T>,
37 F: Fn(T) -> U,
38{
39 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
40 let result = self.parser.parse(db, entry)?;
41 Ok((self.f)(result))
42 }
43}
44
45pub struct MapWithDb<P, F, T> {
46 pub(super) parser: P,
47 pub(super) f: F,
48 pub(super) _marker: std::marker::PhantomData<T>,
49}
50
51impl<T, U, P, F> Parser<U> for MapWithDb<P, F, T>
52where
53 P: Parser<T>,
54 F: Fn(&dyn DwarfDb, T) -> U,
55{
56 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
57 let result = self.parser.parse(db, entry)?;
58 Ok((self.f)(db, result))
59 }
60}
61
62pub struct MapWithDbAndEntry<P, F, T> {
63 pub(super) parser: P,
64 pub(super) f: F,
65 pub(super) _marker: std::marker::PhantomData<T>,
66}
67
68impl<T, U, P, F> Parser<U> for MapWithDbAndEntry<P, F, T>
69where
70 P: Parser<T>,
71 F: Fn(&dyn DwarfDb, Die, T) -> U,
72{
73 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
74 let result = self.parser.parse(db, entry)?;
75 Ok((self.f)(db, entry, result))
76 }
77}
78
79pub struct MapRes<P, F, T> {
80 pub(super) parser: P,
81 pub(super) f: F,
82 pub(super) _marker: std::marker::PhantomData<T>,
83}
84
85impl<T, U, P, F> Parser<U> for MapRes<P, F, T>
86where
87 P: Parser<T>,
88 F: Fn(T) -> Result<U>,
89{
90 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
91 let result = self.parser.parse(db, entry)?;
92 (self.f)(result)
93 }
94}
95
96pub struct Then<P1, P2, T> {
98 pub(super) first: P1,
99 pub(super) second: P2,
100 pub(super) _marker: std::marker::PhantomData<T>,
101}
102
103impl<U, P1, P2> Parser<U> for Then<P1, P2, Die>
104where
105 P1: Parser<Die>,
106 P2: Parser<U>,
107{
108 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
109 let intermediate = self.first.parse(db, entry)?;
110 self.second.parse(db, intermediate)
111 }
112}
113
114impl<U, P1, P2> Parser<Option<U>> for Then<P1, P2, Option<Die>>
115where
116 P1: Parser<Option<Die>>,
117 P2: Parser<U>,
118{
119 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<Option<U>> {
120 self.first
121 .parse(db, entry)?
122 .map(|intermediate| self.second.parse(db, intermediate))
123 .transpose()
124 }
125}
126
127impl<U, P1, P2> Parser<U> for Then<P1, P2, Result<Die>>
128where
129 P1: Parser<Result<Die>>,
130 P2: Parser<U>,
131{
132 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<U> {
133 self.first
134 .parse(db, entry)?
135 .and_then(|intermediate| self.second.parse(db, intermediate))
136 }
137}
138
139pub struct Filter<P> {
141 pub(super) parser: P,
142}
143
144impl<T, P> Parser<Option<T>> for Filter<P>
145where
146 P: Parser<T>,
147{
148 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<Option<T>> {
149 Ok(self.parser.parse(db, entry).ok())
150 }
151}
152
153pub struct Context<P> {
155 pub(super) parser: P,
156 pub(super) context: String,
157}
158
159impl<T, P> Parser<T> for Context<P>
160where
161 P: Parser<T>,
162{
163 fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<T> {
164 self.parser
165 .parse(db, entry)
166 .with_context(|| entry.format_with_location(db, &self.context))
167 }
168}
169
170pub fn all<T>(parsers: T) -> All<T> {
172 All { parsers }
173}
174
175pub struct All<T> {
176 pub(super) parsers: T,
177}
178
179macro_rules! impl_parse_all_for_tuples {
187 (
188 $($P:ident, $T:ident, $idx:tt),*
189 ) => {
190 impl<$($T, $P,)*> Parser< ($($T,)*)> for All<($($P,)*)>
191 where
192 $($P: Parser< $T>),*
193 {
194 fn parse(&self, _db: &dyn DwarfDb, _entry: Die) -> anyhow::Result<($($T,)*)> {
195
196 Ok((
197 $(
198 self.parsers.$idx.parse(_db, _entry)?,
199 )*
200 ))
201 }
202 }
203 };
204}
205
206impl_parse_all_for_tuples!();
208impl_parse_all_for_tuples!(P0, T0, 0);
209impl_parse_all_for_tuples!(P0, T0, 0, P1, T1, 1);
210impl_parse_all_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2);
211impl_parse_all_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3);
212impl_parse_all_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4);
213impl_parse_all_for_tuples!(P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5);
214impl_parse_all_for_tuples!(
215 P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5, P6, T6, 6
216);
217impl_parse_all_for_tuples!(
218 P0, T0, 0, P1, T1, 1, P2, T2, 2, P3, T3, 3, P4, T4, 4, P5, T5, 5, P6, T6, 6, P7, T7, 7
219);