windows-metadata 0.34.0

Code gen support for the windows crate
Documentation
use super::*;
use std::collections::*;

#[derive(Default, Clone)]
pub struct Cfg {
    types: BTreeMap<&'static str, BTreeSet<Row>>,
    arches: BTreeSet<&'static str>,
}

impl Cfg {
    pub fn new() -> Self {
        Self { types: BTreeMap::new(), arches: BTreeSet::new() }
    }

    pub fn features(&self, namespace: &str) -> Vec<&'static str> {
        let mut compact = Vec::<&'static str>::new();
        for feature in self.types.keys() {
            if !feature.is_empty() && !starts_with(namespace, feature) {
                for pos in 0..compact.len() {
                    if starts_with(feature, unsafe { compact.get_unchecked(pos) }) {
                        compact.remove(pos);
                        break;
                    }
                }
                compact.push(feature);
            }
        }
        compact
    }

    pub fn arches(&self) -> &BTreeSet<&'static str> {
        &self.arches
    }

    pub(crate) fn add_type(&mut self, def: &TypeDef) -> bool {
        self.types.entry(def.namespace()).or_default().insert(def.row.clone())
    }

    pub fn add_feature(&mut self, feature: &'static str) {
        self.types.entry(feature).or_default();
    }

    pub(crate) fn add_attributes(&mut self, attributes: impl Iterator<Item = Attribute>) {
        for attribute in attributes {
            match attribute.name() {
                "SupportedArchitectureAttribute" => {
                    if let Some((_, ConstantValue::I32(value))) = attribute.args().get(0) {
                        if value & 1 == 1 {
                            self.arches.insert("x86");
                        }
                        if value & 2 == 2 {
                            self.arches.insert("x86_64");
                        }
                        if value & 4 == 4 {
                            self.arches.insert("aarch64");
                        }
                    }
                }
                "DeprecatedAttribute" => {
                    self.add_feature("deprecated");
                }
                _ => {}
            }
        }
    }

    pub fn union(&self, other: &Self) -> Self {
        let mut union = Self::new();
        self.types.keys().for_each(|feature| union.add_feature(feature));
        other.types.keys().for_each(|feature| union.add_feature(feature));
        self.arches.iter().for_each(|arch| {
            union.arches.insert(arch);
        });
        other.arches.iter().for_each(|arch| {
            union.arches.insert(arch);
        });
        union
    }
}

fn starts_with(namespace: &str, feature: &str) -> bool {
    if namespace == feature {
        return true;
    }

    if namespace.len() > feature.len() && namespace.as_bytes().get(feature.len()) == Some(&b'.') {
        return namespace.starts_with(feature);
    }

    false
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_starts_with() {
        assert!(starts_with("Windows.Win32.Graphics.Direct3D11on12", "Windows.Win32.Graphics.Direct3D11on12"));
        assert!(starts_with("Windows.Win32.Graphics.Direct3D11on12", "Windows.Win32.Graphics"));
        assert!(!starts_with("Windows.Win32.Graphics.Direct3D11on12", "Windows.Win32.Graphics.Direct3D11"));
        assert!(!starts_with("Windows.Win32.Graphics.Direct3D", "Windows.Win32.Graphics.Direct3D11"));
    }

    #[test]
    fn relative() {
        let def = TypeReader::get().expect_type_def(("Windows.Foundation", "IStringable"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Foundation");

        let def = TypeReader::get().expect_type_def(("Windows.Devices.Display.Core", "DisplayPresentationRate"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 2);
        assert_eq!(namespaces[0], "Windows.Devices.Display.Core");
        assert_eq!(namespaces[1], "Windows.Foundation.Numerics");

        let def = TypeReader::get().expect_type_def(("Windows.Graphics.DirectX.Direct3D11", "Direct3DSurfaceDescription"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Graphics.DirectX.Direct3D11");

        let def = TypeReader::get().expect_type_def(("Windows.Win32.Security.Authorization.UI", "EFFPERM_RESULT_LIST"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 2);
        assert_eq!(namespaces[0], "Windows.Win32.Foundation");
        assert_eq!(namespaces[1], "Windows.Win32.Security.Authorization.UI");

        let def = TypeReader::get().expect_type_def(("Windows.Win32.AI.MachineLearning.WinML", "MLOperatorEdgeDescription"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Win32.AI.MachineLearning.WinML");

        let def = TypeReader::get().get_type(("Windows.Win32.Graphics.Direct3D11on12", "D3D11On12CreateDevice")).unwrap();
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 2);
        assert_eq!(namespaces[0], "Windows.Win32.Graphics.Direct3D");
        assert_eq!(namespaces[1], "Windows.Win32.Graphics.Direct3D11");

        let def = TypeReader::get().expect_type_def(("Windows.Win32.System.Diagnostics.Debug", "CONTEXT"));
        let namespaces = def.cfg().features("Windows");
        assert_eq!(namespaces.len(), 2);
        assert_eq!(namespaces[0], "Windows.Win32.System.Diagnostics.Debug");
        assert_eq!(namespaces[1], "Windows.Win32.System.Kernel");
    }

    #[test]
    fn local() {
        let def = TypeReader::get().expect_type_def(("Windows.Foundation", "IStringable"));
        let namespaces = def.cfg().features("Windows.Foundation");
        assert_eq!(namespaces.len(), 0);

        let def = TypeReader::get().expect_type_def(("Windows.Devices.Display.Core", "DisplayPresentationRate"));
        let namespaces = def.cfg().features("Windows.Devices.Display.Core");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Foundation.Numerics");

        let def = TypeReader::get().expect_type_def(("Windows.Graphics.DirectX.Direct3D11", "Direct3DSurfaceDescription"));
        let namespaces = def.cfg().features("Windows.Graphics.DirectX.Direct3D11");
        assert_eq!(namespaces.len(), 0);

        let def = TypeReader::get().expect_type_def(("Windows.Win32.Security.Authorization.UI", "EFFPERM_RESULT_LIST"));
        let namespaces = def.cfg().features("Windows.Win32.Security.Authorization.UI");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Win32.Foundation");

        let def = TypeReader::get().expect_type_def(("Windows.Win32.AI.MachineLearning.WinML", "MLOperatorEdgeDescription"));
        let namespaces = def.cfg().features("Windows.Win32.AI.MachineLearning.WinML");
        assert_eq!(namespaces.len(), 0);

        let def = TypeReader::get().get_type(("Windows.Win32.Graphics.Direct3D11on12", "D3D11On12CreateDevice")).unwrap();
        let namespaces = def.cfg().features("Windows.Win32.Graphics.Direct3D11on12");
        assert_eq!(namespaces.len(), 2);
        assert_eq!(namespaces[0], "Windows.Win32.Graphics.Direct3D");
        assert_eq!(namespaces[1], "Windows.Win32.Graphics.Direct3D11");

        let def = TypeReader::get().expect_type_def(("Windows.Win32.System.Diagnostics.Debug", "CONTEXT"));
        let namespaces = def.cfg().features("Windows.Win32.System.Diagnostics.Debug");
        assert_eq!(namespaces.len(), 1);
        assert_eq!(namespaces[0], "Windows.Win32.System.Kernel");
    }
}