Metadata generation of attributes and constants (#2844)
This commit is contained in:
Родитель
7ce7894932
Коммит
ece23903d1
|
@ -1,6 +1,5 @@
|
|||
/.vscode
|
||||
/.vs
|
||||
/target
|
||||
/temp
|
||||
*.lock
|
||||
*.winmd
|
||||
|
|
|
@ -70,7 +70,7 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb
|
|||
}
|
||||
|
||||
writer.tables.TypeDef.push(winmd::TypeDef {
|
||||
Extends: 0,
|
||||
Extends: winmd::TypeDefOrRef::none(),
|
||||
FieldList: writer.tables.Field.len() as u32,
|
||||
MethodList: writer.tables.MethodDef.len() as u32,
|
||||
Flags: flags.0,
|
||||
|
@ -82,7 +82,7 @@ fn write_interface(writer: &mut winmd::Writer, namespace: &str, name: &str, memb
|
|||
writer.tables.GenericParam.push(writer::GenericParam {
|
||||
Number: number as u16,
|
||||
Flags: 0,
|
||||
Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(),
|
||||
Owner: writer::TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1),
|
||||
Name: writer.strings.insert(generic),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use super::*;
|
||||
use metadata::{AsRow, HasAttributes};
|
||||
|
||||
pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap<&str, &str>, output: &str) -> Result<()> {
|
||||
let mut writer = Writer::new(output);
|
||||
|
@ -22,7 +23,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
|
||||
let generics = &metadata::type_def_generics(def);
|
||||
|
||||
let extends = if let Some(extends) = def.extends() { writer.insert_type_ref(extends.namespace, extends.name) } else { 0 };
|
||||
let extends = if let Some(extends) = def.extends() { writer.insert_type_ref(extends.namespace, extends.name) } else { TypeDefOrRef::none() };
|
||||
|
||||
writer.tables.TypeDef.push(TypeDef {
|
||||
Extends: extends,
|
||||
|
@ -33,11 +34,13 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
TypeNamespace: writer.strings.insert(def.namespace()),
|
||||
});
|
||||
|
||||
let def_ref = writer.tables.TypeDef.len() as u32 - 1;
|
||||
|
||||
for generic in def.generics() {
|
||||
writer.tables.GenericParam.push(GenericParam {
|
||||
Number: generic.number(), // TODO: isn't this just going to be incremental?
|
||||
Flags: 0,
|
||||
Owner: TypeOrMethodDef::TypeDef(writer.tables.TypeDef.len() as u32 - 1).encode(),
|
||||
Owner: TypeOrMethodDef::TypeDef(def_ref),
|
||||
Name: writer.strings.insert(generic.name()),
|
||||
});
|
||||
}
|
||||
|
@ -53,7 +56,7 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
rest => unimplemented!("{rest:?}"),
|
||||
};
|
||||
|
||||
writer.tables.InterfaceImpl.push(InterfaceImpl { Class: writer.tables.TypeDef.len() as u32 - 1, Interface: reference });
|
||||
writer.tables.InterfaceImpl.push(InterfaceImpl { Class: def_ref, Interface: reference });
|
||||
}
|
||||
|
||||
// TODO: if the class is "Apis" then should we sort the fields (constants) and methods (functions) for stability
|
||||
|
@ -63,6 +66,10 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
let signature = writer.insert_field_sig(&ty);
|
||||
|
||||
writer.tables.Field.push(Field { Flags: field.flags().0, Name: writer.strings.insert(field.name()), Signature: signature });
|
||||
|
||||
if let Some(constant) = field.constant() {
|
||||
writer.tables.Constant.push(Constant { Type: constant.usize(0) as u16, Parent: HasConstant::Field(writer.tables.Field.len() as u32 - 1), Value: writer.blobs.insert(&constant.blob(2)) })
|
||||
}
|
||||
}
|
||||
|
||||
for method in def.methods() {
|
||||
|
@ -85,6 +92,44 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
writer.tables.Param.push(Param { Flags: param.flags().0, Sequence: param.sequence(), Name: writer.strings.insert(param.name()) });
|
||||
}
|
||||
}
|
||||
|
||||
for attribute in def.attributes() {
|
||||
let metadata::AttributeType::MemberRef(attribute_ctor) = attribute.ty();
|
||||
assert_eq!(attribute_ctor.name(), ".ctor");
|
||||
let metadata::MemberRefParent::TypeRef(attribute_type) = attribute_ctor.parent();
|
||||
|
||||
let attribute_type_ref = if let TypeDefOrRef::TypeRef(type_ref) = writer.insert_type_ref(attribute_type.namespace(), attribute_type.name()) { MemberRefParent::TypeRef(type_ref) } else { panic!() };
|
||||
|
||||
let signature = attribute_ctor.signature();
|
||||
let return_type = winmd_type(&signature.return_type);
|
||||
let param_types: Vec<Type> = signature.params.iter().map(winmd_type).collect();
|
||||
let signature = writer.insert_method_sig(signature.call_flags, &return_type, ¶m_types);
|
||||
|
||||
writer.tables.MemberRef.push(MemberRef { Class: attribute_type_ref, Name: writer.strings.insert(".ctor"), Signature: signature });
|
||||
|
||||
let mut values = 1u16.to_le_bytes().to_vec(); // prolog
|
||||
let args = attribute.args();
|
||||
let mut named_arg_count = false;
|
||||
|
||||
for (index, (name, value)) in args.iter().enumerate() {
|
||||
value_blob(value, &mut values);
|
||||
|
||||
if !named_arg_count && !name.is_empty() {
|
||||
named_arg_count = true;
|
||||
let named_arg_count = (args.len() - index) as u16;
|
||||
values.extend_from_slice(&named_arg_count.to_le_bytes());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !named_arg_count {
|
||||
values.extend_from_slice(&0u16.to_le_bytes());
|
||||
}
|
||||
|
||||
let values = writer.blobs.insert(&values);
|
||||
|
||||
writer.tables.CustomAttribute.push(CustomAttribute { Parent: HasAttribute::TypeDef(def_ref), Type: AttributeType::MemberRef(writer.tables.MemberRef.len() as u32 - 1), Value: values });
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: In theory, `config` could instruct this function to balance the types across a number of winmd files
|
||||
|
@ -92,6 +137,35 @@ pub fn from_reader(reader: &metadata::Reader, config: std::collections::BTreeMap
|
|||
write_to_file(output, writer.into_stream()).map_err(|err| err.with_path(output))
|
||||
}
|
||||
|
||||
// TODO: need a Blob type for writing
|
||||
fn value_blob(value: &metadata::Value, blob: &mut Vec<u8>) {
|
||||
match value {
|
||||
metadata::Value::Bool(value) => {
|
||||
if *value {
|
||||
blob.push(1)
|
||||
} else {
|
||||
blob.push(0)
|
||||
}
|
||||
}
|
||||
metadata::Value::U32(value) => blob.extend_from_slice(&value.to_le_bytes()),
|
||||
metadata::Value::I32(value) => blob.extend_from_slice(&value.to_le_bytes()),
|
||||
metadata::Value::U16(value) => blob.extend_from_slice(&value.to_le_bytes()),
|
||||
metadata::Value::U8(value) => blob.extend_from_slice(&value.to_le_bytes()),
|
||||
metadata::Value::EnumDef(_def, value) => value_blob(value, blob),
|
||||
|
||||
metadata::Value::TypeName(value) => {
|
||||
let value = value.to_string();
|
||||
usize_blob(value.len(), blob);
|
||||
blob.extend_from_slice(value.as_bytes());
|
||||
}
|
||||
metadata::Value::String(value) => {
|
||||
usize_blob(value.len(), blob);
|
||||
blob.extend_from_slice(value.as_bytes());
|
||||
}
|
||||
rest => unimplemented!("{rest:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: keep the basic type conversion
|
||||
fn winmd_type(ty: &metadata::Type) -> Type {
|
||||
match ty {
|
||||
|
|
|
@ -1,71 +1,69 @@
|
|||
#![allow(dead_code, clippy::enum_variant_names)]
|
||||
|
||||
/// A `ResolutionScope` is an index into a certain table indicating the scope in which a TypeRef can be resolved.
|
||||
#[derive(Clone)]
|
||||
pub enum ResolutionScope {
|
||||
Module(u32),
|
||||
ModuleRef(u32),
|
||||
AssemblyRef(u32),
|
||||
TypeRef(u32),
|
||||
}
|
||||
|
||||
impl ResolutionScope {
|
||||
pub fn encode(&self) -> u32 {
|
||||
match self {
|
||||
Self::Module(row) => (row + 1) << 2,
|
||||
Self::ModuleRef(row) => ((row + 1) << 2) + 1,
|
||||
Self::AssemblyRef(row) => ((row + 1) << 2) + 2,
|
||||
Self::TypeRef(row) => ((row + 1) << 2) + 3,
|
||||
macro_rules! code {
|
||||
($name:ident($size:literal) $(($table:ident, $code:literal))+) => {
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum $name {
|
||||
$($table(u32),)*
|
||||
}
|
||||
}
|
||||
impl $name {
|
||||
pub fn encode(&self) -> u32 {
|
||||
match self {
|
||||
$(Self::$table(row) => (row.overflowing_add(1).0) << $size | $code,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// A `TypeDefOrRef` is an index into a certain table used to locate a type definition.
|
||||
#[derive(Clone)]
|
||||
pub enum TypeDefOrRef {
|
||||
TypeDef(u32),
|
||||
TypeRef(u32),
|
||||
TypeSpec(u32),
|
||||
code! { AttributeType(3)
|
||||
(MemberRef, 3)
|
||||
}
|
||||
|
||||
// TODO: needs to be called HasCustomAttribute
|
||||
code! { HasAttribute(5)
|
||||
(MethodDef, 0)
|
||||
(Field, 1)
|
||||
(TypeRef, 2)
|
||||
(TypeDef, 3)
|
||||
(Param, 4)
|
||||
(InterfaceImpl, 5)
|
||||
(MemberRef, 6)
|
||||
(TypeSpec, 13)
|
||||
(GenericParam, 19)
|
||||
}
|
||||
|
||||
code! { HasConstant(2)
|
||||
(Field, 0)
|
||||
}
|
||||
|
||||
code! { MemberForwarded(1)
|
||||
(MethodDef, 1)
|
||||
}
|
||||
|
||||
code! { MemberRefParent(3)
|
||||
(TypeRef, 1)
|
||||
}
|
||||
|
||||
code! { TypeDefOrRef(2)
|
||||
(TypeDef, 0)
|
||||
(TypeRef, 1)
|
||||
(TypeSpec, 2)
|
||||
}
|
||||
|
||||
impl TypeDefOrRef {
|
||||
pub fn encode(&self) -> u32 {
|
||||
match self {
|
||||
Self::TypeDef(row) => (row + 1) << 2,
|
||||
Self::TypeRef(row) => ((row + 1) << 2) + 1,
|
||||
Self::TypeSpec(row) => ((row + 1) << 2) + 2,
|
||||
}
|
||||
pub fn none() -> Self {
|
||||
TypeDefOrRef::TypeDef(u32::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
/// A `HasConstant` is an index into a certain table used to identify the parent of a row in the `Constant` table.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum HasConstant {
|
||||
Field(u32),
|
||||
Param(u32),
|
||||
Property(u32),
|
||||
code! { TypeOrMethodDef(1)
|
||||
(TypeDef, 0)
|
||||
}
|
||||
|
||||
impl HasConstant {
|
||||
pub fn encode(&self) -> u32 {
|
||||
match self {
|
||||
Self::Field(row) => (row + 1) << 2,
|
||||
Self::Param(row) => ((row + 1) << 2) + 1,
|
||||
Self::Property(row) => ((row + 1) << 2) + 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A `TypeOrMethodDef` is an index into a certain table used to locate the owner of a generic parameter.
|
||||
#[derive(Clone)]
|
||||
pub enum TypeOrMethodDef {
|
||||
TypeDef(u32),
|
||||
}
|
||||
|
||||
impl TypeOrMethodDef {
|
||||
pub fn encode(&self) -> u32 {
|
||||
match self {
|
||||
Self::TypeDef(row) => (row + 1) << 1,
|
||||
}
|
||||
}
|
||||
code! { ResolutionScope(2)
|
||||
(Module, 0)
|
||||
(ModuleRef, 1)
|
||||
(AssemblyRef, 2)
|
||||
(TypeRef, 3)
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ pub struct Writer {
|
|||
pub blobs: Blobs,
|
||||
pub strings: Strings,
|
||||
pub tables: Tables,
|
||||
pub scopes: HashMap<String, u32>,
|
||||
pub scopes: HashMap<String, ResolutionScope>,
|
||||
// TODO: is this faster than jsut using a single HashMap with a (String,String) key?
|
||||
pub type_refs: HashMap<String, HashMap<String, u32>>,
|
||||
pub type_specs: HashMap<Type, u32>,
|
||||
pub type_refs: HashMap<String, HashMap<String, TypeDefOrRef>>,
|
||||
pub type_specs: HashMap<Type, TypeDefOrRef>,
|
||||
}
|
||||
|
||||
impl Writer {
|
||||
|
@ -36,7 +36,7 @@ impl Writer {
|
|||
type_specs: Default::default(),
|
||||
};
|
||||
|
||||
writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert("<Module>"), ..Default::default() });
|
||||
writer.tables.TypeDef.push(TypeDef { TypeName: writer.strings.insert("<Module>"), Flags: 0, TypeNamespace: 0, Extends: TypeDefOrRef::none(), FieldList: 0, MethodList: 0 });
|
||||
|
||||
let name = name.rsplit_once(&['/', '\\']).map_or(name, |(_, name)| name);
|
||||
|
||||
|
@ -88,7 +88,7 @@ impl Writer {
|
|||
self.blobs.insert(&blob)
|
||||
}
|
||||
|
||||
fn insert_scope(&mut self, namespace: &str) -> u32 {
|
||||
fn insert_scope(&mut self, namespace: &str) -> ResolutionScope {
|
||||
if let Some(scope) = self.scopes.get(namespace) {
|
||||
*scope
|
||||
} else if namespace == "System" {
|
||||
|
@ -97,8 +97,7 @@ impl Writer {
|
|||
MajorVersion: 4,
|
||||
PublicKeyOrToken: self.blobs.insert(&[0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]), // TODO: comment on this
|
||||
..Default::default()
|
||||
}))
|
||||
.encode();
|
||||
}));
|
||||
self.scopes.insert(namespace.to_string(), scope);
|
||||
scope
|
||||
} else {
|
||||
|
@ -111,14 +110,13 @@ impl Writer {
|
|||
RevisionNumber: 0xFF,
|
||||
Flags: metadata::AssemblyFlags::WindowsRuntime.0,
|
||||
..Default::default()
|
||||
}))
|
||||
.encode();
|
||||
}));
|
||||
self.scopes.insert(namespace.to_string(), scope);
|
||||
scope
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> u32 {
|
||||
pub fn insert_type_ref(&mut self, namespace: &str, name: &str) -> TypeDefOrRef {
|
||||
if let Some(key) = self.type_refs.get(namespace) {
|
||||
if let Some(reference) = key.get(name) {
|
||||
return *reference;
|
||||
|
@ -127,12 +125,12 @@ impl Writer {
|
|||
|
||||
let scope = self.insert_scope(namespace);
|
||||
|
||||
let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope })).encode();
|
||||
let reference = TypeDefOrRef::TypeRef(self.tables.TypeRef.push2(TypeRef { TypeName: self.strings.insert(name), TypeNamespace: self.strings.insert(namespace), ResolutionScope: scope }));
|
||||
self.type_refs.entry(namespace.to_string()).or_default().insert(name.to_string(), reference);
|
||||
reference
|
||||
}
|
||||
|
||||
pub fn insert_type_spec(&mut self, ty: Type) -> u32 {
|
||||
pub fn insert_type_spec(&mut self, ty: Type) -> TypeDefOrRef {
|
||||
if let Some(key) = self.type_specs.get(&ty) {
|
||||
return *key;
|
||||
}
|
||||
|
@ -141,8 +139,7 @@ impl Writer {
|
|||
self.type_blob(&ty, &mut blob);
|
||||
let signature = self.blobs.insert(&blob);
|
||||
|
||||
let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature })).encode();
|
||||
|
||||
let reference = TypeDefOrRef::TypeSpec(self.tables.TypeSpec.push2(TypeSpec { Signature: signature }));
|
||||
self.type_specs.insert(ty, reference);
|
||||
reference
|
||||
}
|
||||
|
@ -169,12 +166,12 @@ impl Writer {
|
|||
Type::GUID => {
|
||||
let code = self.insert_type_ref("System", "Guid");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::HRESULT => {
|
||||
let code = self.insert_type_ref("Windows.Foundation", "HResult");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::TypeRef(ty) => {
|
||||
if !ty.generics.is_empty() {
|
||||
|
@ -182,7 +179,7 @@ impl Writer {
|
|||
}
|
||||
let code = self.insert_type_ref(&ty.namespace, &ty.name);
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
|
||||
if !ty.generics.is_empty() {
|
||||
usize_blob(ty.generics.len(), blob);
|
||||
|
@ -195,26 +192,26 @@ impl Writer {
|
|||
Type::BSTR => {
|
||||
let code = self.insert_type_ref("Windows.Win32.Foundation", "BSTR");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::IUnknown => {
|
||||
let code = self.insert_type_ref("Windows.Win32.Foundation", "IUnknown");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::PCWSTR | Type::PWSTR => {
|
||||
let code = self.insert_type_ref("Windows.Win32.Foundation", "PWSTR");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::PCSTR | Type::PSTR => {
|
||||
let code = self.insert_type_ref("Windows.Win32.Foundation", "PSTR");
|
||||
blob.push(metadata::ELEMENT_TYPE_VALUETYPE);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::ConstRef(ty) => {
|
||||
usize_blob(metadata::ELEMENT_TYPE_CMOD_OPT as usize, blob);
|
||||
usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst") as usize, blob);
|
||||
usize_blob(self.insert_type_ref("System.Runtime.CompilerServices", "IsConst").encode() as usize, blob);
|
||||
usize_blob(metadata::ELEMENT_TYPE_BYREF as usize, blob);
|
||||
self.type_blob(ty, blob);
|
||||
}
|
||||
|
@ -237,7 +234,7 @@ impl Writer {
|
|||
Type::Type => {
|
||||
let code = self.insert_type_ref("System", "Type");
|
||||
blob.push(metadata::ELEMENT_TYPE_CLASS);
|
||||
usize_blob(code as usize, blob);
|
||||
usize_blob(code.encode() as usize, blob);
|
||||
}
|
||||
Type::MutPtr(ty, pointers) | Type::ConstPtr(ty, pointers) => {
|
||||
for _ in 0..*pointers {
|
||||
|
@ -258,7 +255,8 @@ fn round(size: usize, round: usize) -> usize {
|
|||
(size + round) & !round
|
||||
}
|
||||
|
||||
fn usize_blob(value: usize, blob: &mut Vec<u8>) {
|
||||
// TODO: need a Blob type for writing
|
||||
pub fn usize_blob(value: usize, blob: &mut Vec<u8>) {
|
||||
// See II.23.2 in ECMA-335
|
||||
assert!(value < 0x20000000);
|
||||
|
||||
|
|
|
@ -60,17 +60,15 @@ pub struct ClassLayout {
|
|||
pub Parent: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Constant {
|
||||
pub Type: u16,
|
||||
pub Parent: u32,
|
||||
pub Parent: HasConstant,
|
||||
pub Value: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CustomAttribute {
|
||||
pub Parent: u32,
|
||||
pub Type: u32,
|
||||
pub Parent: HasAttribute,
|
||||
pub Type: AttributeType,
|
||||
pub Value: u32,
|
||||
}
|
||||
|
||||
|
@ -81,11 +79,10 @@ pub struct Field {
|
|||
pub Signature: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GenericParam {
|
||||
pub Number: u16,
|
||||
pub Flags: u16,
|
||||
pub Owner: u32,
|
||||
pub Owner: TypeOrMethodDef,
|
||||
pub Name: u32,
|
||||
}
|
||||
|
||||
|
@ -97,15 +94,13 @@ pub struct ImplMap {
|
|||
pub ImportScope: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct InterfaceImpl {
|
||||
pub Class: u32,
|
||||
pub Interface: u32,
|
||||
pub Interface: TypeDefOrRef,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct MemberRef {
|
||||
pub Class: u32,
|
||||
pub Class: MemberRefParent,
|
||||
pub Name: u32,
|
||||
pub Signature: u32,
|
||||
}
|
||||
|
@ -154,19 +149,17 @@ pub struct Property {
|
|||
pub Type: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TypeDef {
|
||||
pub Flags: u32,
|
||||
pub TypeName: u32,
|
||||
pub TypeNamespace: u32,
|
||||
pub Extends: u32,
|
||||
pub Extends: TypeDefOrRef,
|
||||
pub FieldList: u32,
|
||||
pub MethodList: u32,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TypeRef {
|
||||
pub ResolutionScope: u32,
|
||||
pub ResolutionScope: ResolutionScope,
|
||||
pub TypeName: u32,
|
||||
pub TypeNamespace: u32,
|
||||
}
|
||||
|
@ -183,12 +176,12 @@ impl Tables {
|
|||
}
|
||||
|
||||
let resolution_scope = metadata::coded_index_size(&[self.Module.len(), self.ModuleRef.len(), self.AssemblyRef.len(), self.TypeRef.len()]);
|
||||
|
||||
let type_def_or_ref = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.TypeSpec.len()]);
|
||||
|
||||
let has_constant = metadata::coded_index_size(&[self.Field.len(), self.Param.len(), self.Property.len()]);
|
||||
|
||||
let type_or_method_def = metadata::coded_index_size(&[self.TypeDef.len(), self.MethodDef.len()]);
|
||||
let member_ref_parent = metadata::coded_index_size(&[self.TypeDef.len(), self.TypeRef.len(), self.ModuleRef.len(), self.MethodDef.len(), self.TypeSpec.len()]);
|
||||
let custom_attribute_type = metadata::coded_index_size(&[self.MethodDef.len(), self.MemberRef.len(), 0, 0, 0]);
|
||||
let has_custom_attribute = metadata::coded_index_size(&[self.MethodDef.len(), self.Field.len(), self.TypeRef.len(), self.TypeDef.len(), self.Param.len(), self.InterfaceImpl.len(), self.MemberRef.len(), self.Module.len(), 0, 0, 0, self.ModuleRef.len(), self.TypeSpec.len(), 0, self.AssemblyRef.len(), 0, 0, 0, self.GenericParam.len(), 0, 0]);
|
||||
|
||||
let valid_tables: u64 = 1 << 0 | // Module
|
||||
1 << 0x01 | // TypeRef
|
||||
|
@ -254,7 +247,7 @@ impl Tables {
|
|||
}
|
||||
|
||||
for x in self.TypeRef {
|
||||
buffer.write_code(x.ResolutionScope, resolution_scope);
|
||||
buffer.write_code(x.ResolutionScope.encode(), resolution_scope);
|
||||
buffer.write_u32(x.TypeName);
|
||||
buffer.write_u32(x.TypeNamespace);
|
||||
}
|
||||
|
@ -263,7 +256,7 @@ impl Tables {
|
|||
buffer.write_u32(x.Flags);
|
||||
buffer.write_u32(x.TypeName);
|
||||
buffer.write_u32(x.TypeNamespace);
|
||||
buffer.write_code(x.Extends, type_def_or_ref);
|
||||
buffer.write_code(x.Extends.encode(), type_def_or_ref);
|
||||
buffer.write_index(x.FieldList, self.Field.len());
|
||||
buffer.write_index(x.MethodList, self.MethodDef.len());
|
||||
}
|
||||
|
@ -291,12 +284,24 @@ impl Tables {
|
|||
|
||||
for x in self.InterfaceImpl {
|
||||
buffer.write_index(x.Class, self.TypeDef.len());
|
||||
buffer.write_code(x.Interface, type_def_or_ref);
|
||||
buffer.write_code(x.Interface.encode(), type_def_or_ref);
|
||||
}
|
||||
|
||||
for x in self.MemberRef {
|
||||
buffer.write_code(x.Class.encode(), member_ref_parent);
|
||||
buffer.write_u32(x.Name);
|
||||
buffer.write_u32(x.Signature);
|
||||
}
|
||||
|
||||
for x in self.Constant {
|
||||
buffer.write_u16(x.Type);
|
||||
buffer.write_code(x.Parent, has_constant);
|
||||
buffer.write_code(x.Parent.encode(), has_constant);
|
||||
buffer.write_u32(x.Value);
|
||||
}
|
||||
|
||||
for x in self.CustomAttribute {
|
||||
buffer.write_code(x.Parent.encode(), has_custom_attribute);
|
||||
buffer.write_code(x.Type.encode(), custom_attribute_type);
|
||||
buffer.write_u32(x.Value);
|
||||
}
|
||||
|
||||
|
@ -331,7 +336,7 @@ impl Tables {
|
|||
for x in self.GenericParam {
|
||||
buffer.write_u16(x.Number);
|
||||
buffer.write_u16(x.Flags);
|
||||
buffer.write_code(x.Owner, type_or_method_def);
|
||||
buffer.write_code(x.Owner.encode(), type_or_method_def);
|
||||
buffer.write_u32(x.Name);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ pub enum Value {
|
|||
EnumDef(TypeDef, Box<Self>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MethodDefSig {
|
||||
pub call_flags: MethodCallAttributes,
|
||||
pub return_type: Type,
|
||||
|
|
|
@ -63,10 +63,13 @@ impl Attribute {
|
|||
let AttributeType::MemberRef(member) = self.ty();
|
||||
let mut sig = member.blob(2);
|
||||
let mut values = self.blob(2);
|
||||
let _prolog = values.read_u16();
|
||||
let _this_and_gen_param_count = sig.read_usize();
|
||||
let prolog = values.read_u16();
|
||||
std::debug_assert_eq!(prolog, 1);
|
||||
let this_and_gen_param_count = sig.read_usize();
|
||||
std::debug_assert_eq!(this_and_gen_param_count, 32);
|
||||
let fixed_arg_count = sig.read_usize();
|
||||
let _ret_type = sig.read_usize();
|
||||
let ret_type = sig.read_usize();
|
||||
std::debug_assert_eq!(ret_type, 1);
|
||||
let mut args = Vec::with_capacity(fixed_arg_count);
|
||||
let reader = self.reader();
|
||||
|
||||
|
@ -219,6 +222,16 @@ impl MemberRef {
|
|||
pub fn name(&self) -> &'static str {
|
||||
self.str(1)
|
||||
}
|
||||
|
||||
pub fn signature(&self) -> MethodDefSig {
|
||||
let reader = self.reader();
|
||||
let mut blob = self.blob(2);
|
||||
let call_flags = MethodCallAttributes(blob.read_usize() as u8);
|
||||
let params = blob.read_usize();
|
||||
let return_type = reader.type_from_blob(&mut blob, None, &[]);
|
||||
|
||||
MethodDefSig { call_flags, return_type, params: (0..params).map(|_| reader.type_from_blob(&mut blob, None, &[])).collect() }
|
||||
}
|
||||
}
|
||||
|
||||
impl MethodDef {
|
||||
|
|
|
@ -16,9 +16,9 @@ Options:
|
|||
);
|
||||
} else {
|
||||
match windows_bindgen::bindgen(args) {
|
||||
Ok(ok) => println!("{}", ok),
|
||||
Ok(ok) => println!("{ok}"),
|
||||
Err(error) => {
|
||||
eprintln!("{}", error);
|
||||
eprintln!("{error}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче