xidl-parser 0.50.2

A IDL codegen.
Documentation
use super::*;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ConstrTypeDcl {
    StructForwardDcl(StructForwardDcl),
    StructDcl(StructDcl),
    EnumDcl(EnumDcl),
    UnionForwardDcl(UnionForwardDcl),
    UnionDef(UnionDef),
    BitsetDcl(BitsetDcl),
    BitmaskDcl(BitmaskDcl),
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UnionForwardDcl {
    pub annotations: Vec<Annotation>,
    pub ident: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct UnionDef {
    pub annotations: Vec<Annotation>,
    pub ident: String,
    pub switch_type_spec: SwitchTypeSpec,
    pub case: Vec<Case>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Case {
    pub label: Vec<CaseLabel>,
    pub element: ElementSpec,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum CaseLabel {
    Value(ConstExpr),
    Default,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ElementSpec {
    pub annotations: Vec<Annotation>,
    pub ty: ElementSpecTy,
    pub value: Declarator,
    pub field_id: Option<u32>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ElementSpecTy {
    TypeSpec(TypeSpec),
    ConstrTypeDcl(ConstrTypeDcl),
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum SwitchTypeSpec {
    IntegerType(IntegerType),
    CharType,
    WideCharType,
    BooleanType,
    ScopedName(ScopedName),
    OctetType,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BitsetDcl {
    pub annotations: Vec<Annotation>,
    pub ident: String,
    pub parent: Option<ScopedName>,
    pub field: Vec<BitField>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum BitFieldType {
    Bool,
    Octec,
    SignedInt,
    UnsignedInt,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BitField {
    pub ident: String,
    pub pos: PositiveIntConst,
    pub ty: Option<BitFieldType>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BitmaskDcl {
    pub annotations: Vec<Annotation>,
    pub ident: String,
    pub value: Vec<BitValue>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BitValue {
    pub position: usize,
    pub annotations: Vec<Annotation>,
    pub ident: String,
}

impl UnionDef {
    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
        config.resolve_for_annotations(&self.annotations)
    }
}

impl BitsetDcl {
    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
        config.resolve_for_annotations(&self.annotations)
    }
}

impl BitmaskDcl {
    pub fn serialize_kind(&self, config: &SerializeConfig) -> SerializeKind {
        config.resolve_for_annotations(&self.annotations)
    }
}

impl From<crate::typed_ast::ConstrTypeDcl> for ConstrTypeDcl {
    fn from(value: crate::typed_ast::ConstrTypeDcl) -> Self {
        match value {
            crate::typed_ast::ConstrTypeDcl::StructDcl(value) => value.into(),
            crate::typed_ast::ConstrTypeDcl::UnionDcl(value) => value.into(),
            crate::typed_ast::ConstrTypeDcl::EnumDcl(value) => Self::EnumDcl(value.into()),
            crate::typed_ast::ConstrTypeDcl::BitsetDcl(value) => Self::BitsetDcl(value.into()),
            crate::typed_ast::ConstrTypeDcl::BitmaskDcl(value) => Self::BitmaskDcl(value.into()),
        }
    }
}

impl From<crate::typed_ast::StructDcl> for ConstrTypeDcl {
    fn from(value: crate::typed_ast::StructDcl) -> Self {
        match value {
            crate::typed_ast::StructDcl::StructForwardDcl(value) => {
                Self::StructForwardDcl(value.into())
            }
            crate::typed_ast::StructDcl::StructDef(value) => Self::StructDcl(value.into()),
        }
    }
}

impl From<crate::typed_ast::UnionDcl> for ConstrTypeDcl {
    fn from(value: crate::typed_ast::UnionDcl) -> Self {
        match value {
            crate::typed_ast::UnionDcl::UnionForwardDcl(value) => {
                Self::UnionForwardDcl(value.into())
            }
            crate::typed_ast::UnionDcl::UnionDef(value) => Self::UnionDef(value.into()),
        }
    }
}

impl From<crate::typed_ast::UnionForwardDcl> for UnionForwardDcl {
    fn from(value: crate::typed_ast::UnionForwardDcl) -> Self {
        Self {
            annotations: vec![],
            ident: value.0.0,
        }
    }
}

impl From<crate::typed_ast::UnionDef> for UnionDef {
    fn from(value: crate::typed_ast::UnionDef) -> Self {
        let mut cases = value
            .case
            .into_iter()
            .map(Case::from)
            .collect::<Vec<Case>>();
        let mut member_ids = std::collections::HashMap::new();
        let mut next_field_id = 1u32;

        for case in &mut cases {
            let name = declarator_name(&case.element.value).to_string();
            if let Some(id) = case.element.field_id {
                let entry = member_ids.entry(name.clone()).or_insert(id);
                case.element.field_id = Some(*entry);
            } else if let Some(existing) = member_ids.get(&name) {
                case.element.field_id = Some(*existing);
            } else {
                member_ids.insert(name, next_field_id);
                case.element.field_id = Some(next_field_id);
                next_field_id += 1;
            }
        }

        Self {
            annotations: vec![],
            ident: value.ident.0,
            switch_type_spec: value.switch_type_spec.into(),
            case: cases,
        }
    }
}

impl From<crate::typed_ast::Case> for Case {
    fn from(value: crate::typed_ast::Case) -> Self {
        Self {
            label: value.label.into_iter().map(Into::into).collect(),
            element: value.element.into(),
        }
    }
}

impl From<crate::typed_ast::CaseLabel> for CaseLabel {
    fn from(value: crate::typed_ast::CaseLabel) -> Self {
        match value {
            crate::typed_ast::CaseLabel::Case(value) => Self::Value(value.into()),
            crate::typed_ast::CaseLabel::Default => Self::Default,
        }
    }
}

impl From<crate::typed_ast::ElementSpec> for ElementSpec {
    fn from(value: crate::typed_ast::ElementSpec) -> Self {
        let annotations = expand_annotations(value.annotations);
        Self {
            field_id: annotation_id_value(&annotations),
            annotations,
            ty: value.ty.into(),
            value: value.value.into(),
        }
    }
}

impl From<crate::typed_ast::ElementSpecTy> for ElementSpecTy {
    fn from(value: crate::typed_ast::ElementSpecTy) -> Self {
        match value {
            crate::typed_ast::ElementSpecTy::TypeSpec(value) => Self::TypeSpec(value.into()),
            crate::typed_ast::ElementSpecTy::ConstrTypeDcl(value) => {
                Self::ConstrTypeDcl(value.into())
            }
        }
    }
}

impl From<crate::typed_ast::SwitchTypeSpec> for SwitchTypeSpec {
    fn from(value: crate::typed_ast::SwitchTypeSpec) -> Self {
        match value {
            crate::typed_ast::SwitchTypeSpec::IntegerType(value) => Self::IntegerType(value.into()),
            crate::typed_ast::SwitchTypeSpec::CharType(_) => Self::CharType,
            crate::typed_ast::SwitchTypeSpec::WideCharType(_) => Self::WideCharType,
            crate::typed_ast::SwitchTypeSpec::BooleanType(_) => Self::BooleanType,
            crate::typed_ast::SwitchTypeSpec::ScopedName(value) => Self::ScopedName(value.into()),
            crate::typed_ast::SwitchTypeSpec::OctetType(_) => Self::OctetType,
        }
    }
}

impl From<crate::typed_ast::BitsetDcl> for BitsetDcl {
    fn from(value: crate::typed_ast::BitsetDcl) -> Self {
        let mut field = Vec::new();
        for bitfield in value.field {
            let pos = bitfield.spec.pos;
            let ty = bitfield.spec.dst_ty.map(Into::into);
            for ident in bitfield.ident {
                field.push(BitField {
                    ident: ident.0,
                    pos: pos.clone().into(),
                    ty: ty.clone(),
                });
            }
        }

        Self {
            annotations: vec![],
            ident: value.ident.0,
            parent: value.parent.map(Into::into),
            field,
        }
    }
}

impl From<crate::typed_ast::DestinationType> for BitFieldType {
    fn from(value: crate::typed_ast::DestinationType) -> Self {
        match value {
            crate::typed_ast::DestinationType::BooleanType(_) => Self::Bool,
            crate::typed_ast::DestinationType::OctetType(_) => Self::Octec,
            crate::typed_ast::DestinationType::IntegerType(value) => {
                if matches!(value, crate::typed_ast::IntegerType::SignedInt(_)) {
                    Self::SignedInt
                } else {
                    Self::UnsignedInt
                }
            }
        }
    }
}

impl From<crate::typed_ast::BitmaskDcl> for BitmaskDcl {
    fn from(value: crate::typed_ast::BitmaskDcl) -> Self {
        let mut bits = vec![];
        for (idx, bitvalue) in value.value.into_iter().enumerate() {
            let mut position = idx;
            for annotation in &bitvalue.annotations {
                let crate::typed_ast::AnnotationName::Builtin(name) = &annotation.name else {
                    continue;
                };
                if !name.eq_ignore_ascii_case("position") {
                    continue;
                }

                let Some(crate::typed_ast::AnnotationParams::Raw(v)) = &annotation.params else {
                    continue;
                };

                if let Ok(v) = v.parse::<usize>() {
                    position = v;
                }
            }
            let mut bit: BitValue = bitvalue.into();
            bit.position = position;
            bits.push(bit);
        }
        Self {
            annotations: vec![],
            ident: value.ident.0,
            value: bits,
        }
    }
}

impl From<crate::typed_ast::BitValue> for BitValue {
    fn from(value: crate::typed_ast::BitValue) -> Self {
        Self {
            position: 0,
            annotations: expand_annotations(value.annotations),
            ident: value.ident.0,
        }
    }
}

fn declarator_name(value: &Declarator) -> &str {
    match value {
        Declarator::SimpleDeclarator(value) => &value.0,
        Declarator::ArrayDeclarator(value) => &value.ident,
    }
}