use std::sync::Arc;
use crate::{
metadata::{
security::{PermissionSet, Security, SecurityAction},
streams::Blob,
tables::{
CodedIndex, CodedIndexType, DeclSecurity, DeclSecurityRc, TableInfoRef, TableRow,
},
token::Token,
typesystem::CilTypeReference,
},
Result,
};
#[derive(Clone, Debug)]
pub struct DeclSecurityRaw {
pub rid: u32,
pub token: Token,
pub offset: usize,
pub action: u16,
pub parent: CodedIndex,
pub permission_set: u32,
}
impl DeclSecurityRaw {
pub fn apply<F>(&self, get_ref: F, blob: &Blob) -> Result<()>
where
F: Fn(&CodedIndex) -> CilTypeReference,
{
let blob_data = blob.get(self.permission_set as usize)?;
let permission_set = Arc::new(PermissionSet::new(blob_data)?);
let action = SecurityAction::from(self.action);
let parent = get_ref(&self.parent);
match parent {
CilTypeReference::TypeDef(typedef) => {
if let Some(strong_ref) = typedef.upgrade() {
strong_ref
.security
.set(Security {
action,
permission_set,
})
.ok();
}
Ok(())
}
CilTypeReference::MethodDef(method) => {
if let Some(method) = method.upgrade() {
method
.security
.set(Security {
action,
permission_set,
})
.ok();
}
Ok(())
}
CilTypeReference::Assembly(assembly) => {
assembly
.security
.set(Security {
action,
permission_set,
})
.ok();
Ok(())
}
_ => Err(malformed_error!(
"Invalid parent for {0}",
self.token.value()
)),
}
}
pub fn to_owned<F>(&self, get_ref: F, blob: &Blob) -> Result<DeclSecurityRc>
where
F: Fn(&CodedIndex) -> CilTypeReference,
{
let blob_data = blob.get(self.permission_set as usize)?;
let permission_set = Arc::new(PermissionSet::new(blob_data)?);
let action = SecurityAction::from(self.action);
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(DeclSecurity {
rid: self.rid,
token: self.token,
offset: self.offset,
action,
parent,
permission_set,
custom_attributes: Arc::new(boxcar::Vec::new()),
}))
}
}
impl TableRow for DeclSecurityRaw {
#[rustfmt::skip]
fn row_size(sizes: &TableInfoRef) -> u32 {
u32::from(
2 +
sizes.coded_index_bytes(CodedIndexType::HasDeclSecurity) +
sizes.blob_bytes()
)
}
}