use std::sync::{atomic::Ordering, Arc};
use crate::{
metadata::{
imports::Imports,
method::MethodMap,
streams::Strings,
tables::{
CodedIndex, CodedIndexType, ImplMap, ImplMapRc, ModuleRefMap, TableId, TableInfoRef,
TableRow,
},
token::Token,
typesystem::CilTypeReference,
},
Result,
};
#[derive(Clone, Debug)]
pub struct ImplMapRaw {
pub rid: u32,
pub token: Token,
pub offset: usize,
pub mapping_flags: u32,
pub member_forwarded: CodedIndex,
pub import_name: u32,
pub import_scope: u32,
}
impl ImplMapRaw {
pub fn apply(
&self,
strings: &Strings,
modules: &ModuleRefMap,
methods: &MethodMap,
imports: &Imports,
) -> Result<()> {
match self.member_forwarded.tag {
TableId::MethodDef => match methods.get(&self.member_forwarded.token) {
Some(method) => {
method
.value()
.flags_pinvoke
.store(self.mapping_flags, Ordering::Relaxed);
match modules.get(&Token::new(self.import_scope | 0x1A00_0000)) {
Some(module_ref) => {
let import_name = strings.get(self.import_name as usize)?.to_string();
imports.add_method(
import_name,
&self.token,
method.value().clone(),
module_ref.value(),
)
}
None => Err(malformed_error!(
"Failed to resolve import_scope token - {}",
self.import_scope | 0x1A00_0000
)),
}
}
None => Err(malformed_error!(
"Failed to resolve member_forwarded token - {}",
self.member_forwarded.token.value()
)),
},
_ => Err(malformed_error!(
"Invalid member_forwarded token - {}",
self.member_forwarded.token.value()
)),
}
}
pub fn to_owned<F>(
&self,
get_ref: F,
strings: &Strings,
modules: &ModuleRefMap,
) -> Result<ImplMapRc>
where
F: Fn(&CodedIndex) -> CilTypeReference,
{
let member_forwarded = match get_ref(&self.member_forwarded) {
CilTypeReference::MethodDef(method_def) => match method_def.upgrade() {
Some(method) => {
method
.flags_pinvoke
.store(self.mapping_flags, Ordering::Relaxed);
method
}
None => {
return Err(malformed_error!(
"Failed to upgrade MethodDef weak reference - {}",
self.member_forwarded.token.value()
))
}
},
_ => {
return Err(malformed_error!(
"Invalid member_forwarded token - {}",
self.member_forwarded.token.value()
))
}
};
Ok(Arc::new(ImplMap {
rid: self.rid,
token: self.token,
offset: self.offset,
mapping_flags: self.mapping_flags,
member_forwarded,
import_name: strings.get(self.import_name as usize)?.to_string(),
import_scope: match modules.get(&Token::new(self.import_scope | 0x1A00_0000)) {
Some(module_ref) => module_ref.value().clone(),
None => {
return Err(malformed_error!(
"Failed to resolve import_scope token - {}",
self.import_scope | 0x1A00_0000
))
}
},
}))
}
}
impl TableRow for ImplMapRaw {
#[rustfmt::skip]
fn row_size(sizes: &TableInfoRef) -> u32 {
u32::from(
2 +
sizes.coded_index_bytes(CodedIndexType::MemberForwarded) +
sizes.str_bytes() +
sizes.table_index_bytes(TableId::ModuleRef)
)
}
}