use std::sync::Arc;
use crate::{
metadata::{
marshalling::parse_marshalling_descriptor,
streams::Blob,
tables::{
CodedIndex, CodedIndexType, FieldMap, FieldMarshal, FieldMarshalRc, ParamMap, TableId,
TableInfoRef, TableRow,
},
token::Token,
typesystem::CilTypeReference,
},
Result,
};
#[derive(Clone, Debug)]
pub struct FieldMarshalRaw {
pub rid: u32,
pub token: Token,
pub offset: usize,
pub parent: CodedIndex,
pub native_type: u32,
}
impl FieldMarshalRaw {
pub fn apply(&self, blob: &Blob, params: &ParamMap, fields: &FieldMap) -> Result<()> {
let marshal = parse_marshalling_descriptor(blob.get(self.native_type as usize)?)?;
match self.parent.tag {
TableId::Field => match fields.get(&self.parent.token) {
Some(field) => field
.value()
.marshal
.set(marshal)
.map_err(|_| malformed_error!("Marshal info already set for field")),
None => Err(malformed_error!(
"Failed to resolve field token - {}",
self.parent.token.value()
)),
},
TableId::Param => match params.get(&self.parent.token) {
Some(param) => param
.value()
.marshal
.set(marshal)
.map_err(|_| malformed_error!("Marshal info already set for param")),
None => Err(malformed_error!(
"Failed to resolve param token - {}",
self.parent.token.value()
)),
},
_ => Err(malformed_error!(
"Invalid parent token - {}",
self.parent.token.value()
)),
}
}
pub fn to_owned<F>(&self, get_ref: F, blob: &Blob) -> Result<FieldMarshalRc>
where
F: Fn(&CodedIndex) -> CilTypeReference,
{
let parent = get_ref(&self.parent);
if matches!(parent, CilTypeReference::None) {
return Err(malformed_error!(
"Failed to resolve parent token - {}",
self.parent.token.value()
));
}
Ok(Arc::new(FieldMarshal {
rid: self.rid,
token: self.token,
offset: self.offset,
parent,
native_type: Arc::new(parse_marshalling_descriptor(
blob.get(self.native_type as usize)?,
)?),
}))
}
}
impl TableRow for FieldMarshalRaw {
#[rustfmt::skip]
fn row_size(sizes: &TableInfoRef) -> u32 {
u32::from(
sizes.coded_index_bytes(CodedIndexType::HasFieldMarshal) +
sizes.blob_bytes()
)
}
}