Skip to main content

type_crawler/types/
field.rs

1use std::fmt::Display;
2
3use crate::{
4    Env, TypeKind, Types,
5    error::{InvalidAstSnafu, ParseError},
6};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct Field {
10    name: Option<String>,
11    kind: TypeKind,
12    constant: bool,
13    volatile: bool,
14    bit_field_width: Option<u8>,
15}
16
17impl Field {
18    pub fn new(env: &Env, types: &Types, field: &clang::Entity) -> Result<Self, ParseError> {
19        if field.get_kind() != clang::EntityKind::FieldDecl {
20            return InvalidAstSnafu { message: format!("Expected FieldDecl, found: {field:?}") }
21                .fail();
22        }
23
24        let name = if field.is_anonymous() {
25            None
26        } else {
27            let name = field.get_name().ok_or_else(|| {
28                InvalidAstSnafu { message: format!("FieldDecl without name: {field:?}") }.build()
29            })?;
30            Some(name)
31        };
32        let ty = field.get_type().ok_or_else(|| {
33            InvalidAstSnafu { message: format!("Field without type: {field:?}") }.build()
34        })?;
35
36        let kind = TypeKind::new(env, types, ty)?;
37        let constant = ty.is_const_qualified();
38        let volatile = ty.is_volatile_qualified();
39        let bit_field_width = field.get_bit_field_width().map(|w| w as u8);
40        Ok(Self { name, kind, constant, volatile, bit_field_width })
41    }
42
43    pub fn name(&self) -> Option<&str> {
44        self.name.as_deref()
45    }
46
47    pub fn kind(&self) -> &TypeKind {
48        &self.kind
49    }
50
51    pub fn constant(&self) -> bool {
52        self.constant
53    }
54
55    pub fn volatile(&self) -> bool {
56        self.volatile
57    }
58
59    pub fn bit_field_width(&self) -> Option<u8> {
60        self.bit_field_width
61    }
62
63    pub fn size(&self, types: &Types) -> usize {
64        self.bit_field_width()
65            .map(|w| w.div_ceil(8) as usize)
66            .unwrap_or_else(|| self.kind.size(types))
67    }
68}
69
70impl Display for Field {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        let name = self.name.as_deref().unwrap_or("<anon>");
73        write!(
74            f,
75            "{}: {}{}{:?}",
76            name,
77            if self.constant { "const " } else { "" },
78            if self.volatile { "volatile " } else { "" },
79            self.kind
80        )
81    }
82}