xidl-parser 0.54.0

A IDL codegen.
Documentation
use super::ops::{OperationInfo, ParamInfo, ParamMode, ReturnType};
use super::*;

pub fn operations_from_attr(
    attr: &AttrDcl,
    existing: &std::collections::HashSet<String>,
) -> Vec<OperationInfo> {
    let attrs = match &attr.decl {
        AttrDclInner::ReadonlyAttrSpec(spec) => readonly_attrs(spec),
        AttrDclInner::AttrSpec(spec) => attrs_with_set(spec),
    };

    let mut ops = Vec::new();
    for attr in attrs {
        let get_name = format!("get_attribute_{}", attr.name);
        if !existing.contains(&get_name) {
            ops.push(OperationInfo {
                name: get_name,
                return_ty: ReturnType::Type(attr.ty.clone()),
                params: Vec::new(),
                raises: attr.get_raises,
            });
        }

        if !attr.readonly {
            let set_name = format!("set_attribute_{}", attr.name);
            if !existing.contains(&set_name) {
                ops.push(OperationInfo {
                    name: set_name,
                    return_ty: ReturnType::Void,
                    params: vec![ParamInfo {
                        name: attr.name.clone(),
                        mode: ParamMode::In,
                        ty: attr.ty.clone(),
                    }],
                    raises: attr.set_raises,
                });
            }
        }
    }

    ops
}

struct AttrInfo {
    name: String,
    ty: TypeSpec,
    get_raises: Vec<ScopedName>,
    set_raises: Vec<ScopedName>,
    readonly: bool,
}

fn readonly_attrs(spec: &ReadonlyAttrSpec) -> Vec<AttrInfo> {
    match &spec.declarator {
        ReadonlyAttrDeclarator::SimpleDeclarator(decl) => vec![AttrInfo {
            name: decl.0.clone(),
            ty: spec.ty.clone(),
            get_raises: Vec::new(),
            set_raises: Vec::new(),
            readonly: true,
        }],
        ReadonlyAttrDeclarator::RaisesExpr(raises) => {
            let _ = raises;
            Vec::new()
        }
    }
}

fn attrs_with_set(spec: &AttrSpec) -> Vec<AttrInfo> {
    match &spec.declarator {
        AttrDeclarator::SimpleDeclarator(decls) => decls
            .iter()
            .map(|decl| AttrInfo {
                name: decl.0.clone(),
                ty: spec.ty.clone(),
                get_raises: Vec::new(),
                set_raises: Vec::new(),
                readonly: false,
            })
            .collect(),
        AttrDeclarator::WithRaises { declarator, raises } => {
            let (get_raises, set_raises) = match raises {
                AttrRaisesExpr::Case1(get, set) => (
                    get.expr.0.clone(),
                    set.as_ref()
                        .map(|value| value.expr.0.clone())
                        .unwrap_or_default(),
                ),
                AttrRaisesExpr::SetExcepExpr(set) => (Vec::new(), set.expr.0.clone()),
            };

            vec![AttrInfo {
                name: declarator.0.clone(),
                ty: spec.ty.clone(),
                get_raises,
                set_raises,
                readonly: false,
            }]
        }
    }
}