rudy_dwarf/parser/
option.rs

1//! Option parser implementation using combinators
2
3use anyhow::Result;
4use rudy_types::{Discriminant, OptionLayout};
5
6use super::Parser;
7use crate::{
8    parser::{
9        children::child,
10        combinators::all,
11        enums::{enum_discriminant, enum_named_tuple_variant, PartiallyParsedEnumVariant},
12        primitives::{attr, identity, member_by_tag, resolve_type_shallow},
13    },
14    Die, DwarfDb,
15};
16
17pub struct OptionDefParser;
18
19/// Parser for option types
20///
21/// We'll parse it as a generic enum, and extract out the expect "Some" variant
22pub fn option_def() -> OptionDefParser {
23    OptionDefParser
24}
25
26pub(super) fn parse_option_entry(
27) -> impl Parser<(String, usize, Discriminant, PartiallyParsedEnumVariant)> {
28    all((
29        attr::<String>(gimli::DW_AT_name),
30        attr::<usize>(gimli::DW_AT_byte_size),
31        member_by_tag(gimli::DW_TAG_variant_part).then(
32            enum_discriminant().and(
33                // gets the Some variant and eagerly pulls out the layout and offset
34                // of the inner "__0" member
35                child(enum_named_tuple_variant("Some", (identity(),)).map(
36                    |(discriminant, ((some_offset, some_type_entry),))| {
37                        PartiallyParsedEnumVariant {
38                            discriminant,
39                            layout: some_type_entry,
40                            offset: some_offset,
41                        }
42                    },
43                ))
44                .context("expected Some variant in Option type"),
45            ),
46        ),
47    ))
48    .map(|(name, size, (discriminant, some_variant))| (name, size, discriminant, some_variant))
49}
50
51impl Parser<OptionLayout<Die>> for OptionDefParser {
52    fn parse(&self, db: &dyn DwarfDb, entry: Die) -> Result<OptionLayout<Die>> {
53        tracing::debug!("resolving option type: {}", entry.print(db));
54        let (name, size, discriminant, some_variant) = parse_option_entry().parse(db, entry)?;
55
56        // resolve the some_type
57        let some_type = resolve_type_shallow().parse(db, some_variant.layout)?;
58
59        Ok(OptionLayout {
60            name,
61            some_type,
62            some_offset: some_variant.offset,
63            size,
64            discriminant,
65        })
66    }
67}