windows-metadata 0.60.0

Low-level metadata library for ECMA-335
Documentation
use super::*;

pub trait Decode<'a> {
    fn decode(index: &'a TypeIndex, file: usize, code: usize) -> Self;
}

macro_rules! code {
    ($name:ident($size:literal) $(($table:ident, $code:literal))+) => {
        #[derive(Clone, Debug, Hash, PartialEq, Eq, Ord, PartialOrd)]
        pub enum $name<'a> {
            $($table($table<'a>),)*
        }
        impl<'a> Decode<'a> for $name<'a> {
            fn decode(index: &'a TypeIndex, file: usize, code: usize) -> Self {
                let (kind, row) = (code & ((1 << $size) - 1), (code >> $size) - 1);
                match kind {
                    $($code => Self::$table($table(Row::new(index, file, row))),)*
                    rest => panic!("{rest:?}"),
                }
            }
        }
        impl $name<'_> {
            #[allow(dead_code)]
            pub fn encode(&self) -> usize {
                match self {
                    $(Self::$table(row) => (row.pos() + 1) << $size | $code,)*
                }
            }
        }
        $(
            impl<'a> From<$table<'a>> for $name<'a> {
                fn from(from: $table<'a>) -> Self {
                    Self::$table(from)
                }
            }
        )*
    };
}

code! { AttributeType(3)
    (MethodDef, 2)
    (MemberRef, 3)
}

impl<'a> AttributeType<'a> {
    pub fn parent(&self) -> MemberRefParent<'a> {
        match self {
            Self::MethodDef(row) => row.parent(),
            Self::MemberRef(row) => row.parent(),
        }
    }

    pub fn signature(&self, generics: &[Type]) -> Signature {
        match self {
            Self::MethodDef(row) => row.signature(generics),
            Self::MemberRef(row) => row.signature(generics),
        }
    }
}

code! { HasAttribute(5)
    (MethodDef, 0)
    (Field, 1)
    (TypeRef, 2)
    (TypeDef, 3)
    (MethodParam, 4)
    (InterfaceImpl, 5)
    (MemberRef, 6)
    (TypeSpec, 13)
    (GenericParam, 19)
}

code! { HasConstant(2)
    (Field, 0)
}

code! { MemberForwarded(1)
    (MethodDef, 1)
}

code! { MemberRefParent(3)
    (TypeDef, 0)
    (TypeRef, 1)
}

impl MemberRefParent<'_> {
    pub fn namespace(&self) -> &str {
        match self {
            Self::TypeDef(row) => row.namespace(),
            Self::TypeRef(row) => row.namespace(),
        }
    }

    pub fn name(&self) -> &str {
        match self {
            Self::TypeDef(row) => row.name(),
            Self::TypeRef(row) => row.name(),
        }
    }
}

code! { TypeDefOrRef(2)
    (TypeDef, 0)
    (TypeRef, 1)
    (TypeSpec, 2)
}

code! { TypeOrMethodDef(1)
    (TypeDef, 0)
}

impl TypeDefOrRef<'_> {
    pub fn namespace(&self) -> &str {
        match self {
            Self::TypeDef(row) => row.namespace(),
            Self::TypeRef(row) => row.namespace(),
            rest => panic!("{rest:?}"),
        }
    }

    pub fn name(&self) -> &str {
        match self {
            Self::TypeDef(row) => row.name(),
            Self::TypeRef(row) => row.name(),
            rest => panic!("{rest:?}"),
        }
    }

    pub fn ty(&self, generics: &[Type]) -> Type {
        if let Self::TypeSpec(def) = self {
            return def.ty(generics);
        }

        Type::named(self.namespace(), self.name())
    }
}

code! { ResolutionScope(2)
    (Module, 0)
    (ModuleRef, 1)
    (AssemblyRef, 2)
    (TypeRef, 3)
}