use std::{collections::BTreeMap, sync::Arc};
use crate::{
metadata::{
tables::{MetadataTable, NestedClass, NestedClassRc, TableId, TableInfoRef, TableRow},
token::Token,
typesystem::TypeRegistry,
},
Result,
};
#[derive(Clone, Debug)]
pub struct NestedClassRaw {
pub rid: u32,
pub token: Token,
pub offset: usize,
pub nested_class: u32,
pub enclosing_class: u32,
}
impl NestedClassRaw {
pub fn apply(classes: &MetadataTable<NestedClassRaw>, types: &TypeRegistry) -> Result<()> {
let mut mapping: BTreeMap<u32, Vec<u32>> = BTreeMap::new();
for row in classes {
mapping
.entry(row.enclosing_class | 0x0200_0000)
.or_default()
.push(row.nested_class | 0x0200_0000);
}
for (enclosing, nested_classes) in mapping {
match types.get(&Token::new(enclosing)) {
Some(cil_type) => {
for nested_class in nested_classes {
match types.get(&Token::new(nested_class)) {
Some(nested_type) => {
_ = cil_type.nested_types.push(nested_type.clone().into());
}
None => {
return Err(malformed_error!(
"Failed to resolve nested_class type - {}",
nested_class
))
}
}
}
}
None => {
return Err(malformed_error!(
"Failed to resolve enclosing_class type - {}",
enclosing
))
}
}
}
Ok(())
}
pub fn to_owned(&self, types: &TypeRegistry) -> Result<NestedClassRc> {
Ok(Arc::new(NestedClass {
rid: self.rid,
token: self.token,
offset: self.offset,
nested_class: match types.get(&Token::new(self.nested_class | 0x0200_0000)) {
Some(class) => class.clone(),
None => {
return Err(malformed_error!(
"Failed to resolve nested_class type - {}",
self.nested_class | 0x0200_0000
))
}
},
enclosing_class: match types.get(&Token::new(self.enclosing_class | 0x0200_0000)) {
Some(class) => class.clone(),
None => {
return Err(malformed_error!(
"Failed to resolve enclosing_class - {}",
self.enclosing_class | 0x0200_0000
))
}
},
}))
}
}
impl TableRow for NestedClassRaw {
#[rustfmt::skip]
fn row_size(sizes: &TableInfoRef) -> u32 {
u32::from(
sizes.table_index_bytes(TableId::TypeDef) +
sizes.table_index_bytes(TableId::TypeDef)
)
}
}