use std::sync::Arc;
use crate::{
metadata::{
customattributes::CustomAttributeValueList,
security::{PermissionSet, Security, SecurityAction},
token::Token,
typesystem::CilTypeReference,
},
Result,
};
pub struct DeclSecurity {
pub rid: u32,
pub token: Token,
pub offset: usize,
pub action: SecurityAction,
pub parent: CilTypeReference,
pub permission_set: Arc<PermissionSet>,
pub custom_attributes: CustomAttributeValueList,
}
impl DeclSecurity {
#[must_use]
pub fn is_demand(&self) -> bool {
matches!(self.action, SecurityAction::Demand)
}
#[must_use]
pub fn is_assert(&self) -> bool {
matches!(self.action, SecurityAction::Assert)
}
#[must_use]
pub fn is_deny(&self) -> bool {
matches!(self.action, SecurityAction::Deny)
}
#[must_use]
pub fn is_link_demand(&self) -> bool {
matches!(self.action, SecurityAction::LinkDemand)
}
#[must_use]
pub fn is_inheritance_demand(&self) -> bool {
matches!(self.action, SecurityAction::InheritanceDemand)
}
#[must_use]
pub fn is_unrestricted(&self) -> bool {
self.permission_set.is_unrestricted()
}
#[must_use]
pub fn has_file_io(&self) -> bool {
self.permission_set.has_file_io()
}
#[must_use]
pub fn has_registry(&self) -> bool {
self.permission_set.has_registry()
}
#[must_use]
pub fn has_reflection(&self) -> bool {
self.permission_set.has_reflection()
}
pub fn apply(&self) -> Result<()> {
match &self.parent {
CilTypeReference::TypeDef(typedef) => {
if let Some(strong_ref) = typedef.upgrade() {
strong_ref
.security
.set(Security {
action: self.action,
permission_set: self.permission_set.clone(),
})
.ok();
}
Ok(())
}
CilTypeReference::MethodDef(method) => {
if let Some(method) = method.upgrade() {
method
.security
.set(Security {
action: self.action,
permission_set: self.permission_set.clone(),
})
.ok();
}
Ok(())
}
CilTypeReference::Assembly(assembly) => {
assembly
.security
.set(Security {
action: self.action,
permission_set: self.permission_set.clone(),
})
.ok();
Ok(())
}
_ => Err(malformed_error!(
"Invalid parent for {0}",
self.token.value()
)),
}
}
}