use crate::{
cilassembly::{ChangeRefRc, CilAssembly},
metadata::{
tables::{StandAloneSigRaw, TableDataOwned, TableId},
token::Token,
},
Error, Result,
};
pub struct StandAloneSigBuilder {
signature: Option<Vec<u8>>,
}
impl Default for StandAloneSigBuilder {
fn default() -> Self {
Self::new()
}
}
impl StandAloneSigBuilder {
#[must_use]
pub fn new() -> Self {
Self { signature: None }
}
#[must_use]
pub fn signature(mut self, data: &[u8]) -> Self {
self.signature = Some(data.to_vec());
self
}
pub fn build(self, assembly: &mut CilAssembly) -> Result<ChangeRefRc> {
let signature_data = self
.signature
.ok_or_else(|| Error::ModificationInvalid("signature field is required".to_string()))?;
if signature_data.is_empty() {
return Err(Error::ModificationInvalid(
"signature cannot be empty".to_string(),
));
}
let signature_index = assembly.blob_add(&signature_data)?.placeholder();
let standalonesig_raw = StandAloneSigRaw {
rid: 0,
token: Token::new(0),
offset: 0,
signature: signature_index,
};
assembly.table_row_add(
TableId::StandAloneSig,
TableDataOwned::StandAloneSig(standalonesig_raw),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::factories::table::assemblyref::get_test_assembly;
use std::sync::Arc;
#[test]
fn test_standalonesig_builder_basic() -> Result<()> {
let mut assembly = get_test_assembly()?;
let signature = vec![0x00, 0x01, 0x01]; let _change_ref = StandAloneSigBuilder::new()
.signature(&signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_method_signature() -> Result<()> {
let mut assembly = get_test_assembly()?;
let method_signature = vec![
0x00, 0x02, 0x08, 0x08, 0x0E, ];
let _change_ref = StandAloneSigBuilder::new()
.signature(&method_signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_locals_signature() -> Result<()> {
let mut assembly = get_test_assembly()?;
let locals_signature = vec![
0x07, 0x03, 0x08, 0x0E, 0x1C, ];
let _change_ref = StandAloneSigBuilder::new()
.signature(&locals_signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_generic_signature() -> Result<()> {
let mut assembly = get_test_assembly()?;
let generic_signature = vec![
0x10, 0x01, 0x02, 0x13, 0x00, 0x13, 0x00, 0x08, ];
let _change_ref = StandAloneSigBuilder::new()
.signature(&generic_signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_complex_signature() -> Result<()> {
let mut assembly = get_test_assembly()?;
let complex_signature = vec![
0x00, 0x03, 0x01, 0x1D, 0x08, 0x0F, 0x01, 0x1C, ];
let _change_ref = StandAloneSigBuilder::new()
.signature(&complex_signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_missing_signature() {
let mut assembly = get_test_assembly().unwrap();
let result = StandAloneSigBuilder::new().build(&mut assembly);
assert!(result.is_err());
assert!(result.unwrap_err().to_string().contains("signature"));
}
#[test]
fn test_standalonesig_builder_empty_signature() {
let mut assembly = get_test_assembly().unwrap();
let result = StandAloneSigBuilder::new()
.signature(&[])
.build(&mut assembly);
assert!(result.is_err());
assert!(result
.unwrap_err()
.to_string()
.contains("signature cannot be empty"));
}
#[test]
fn test_standalonesig_builder_default() -> Result<()> {
let mut assembly = get_test_assembly()?;
let signature = vec![0x00, 0x00, 0x01]; let _change_ref = StandAloneSigBuilder::default()
.signature(&signature)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_standalonesig_builder_multiple_signatures() -> Result<()> {
let mut assembly = get_test_assembly()?;
let sig1 = vec![0x00, 0x00, 0x01]; let sig2 = vec![0x00, 0x01, 0x08, 0x08]; let sig3 = vec![0x07, 0x02, 0x08, 0x0E];
let ref1 = StandAloneSigBuilder::new()
.signature(&sig1)
.build(&mut assembly)?;
let ref2 = StandAloneSigBuilder::new()
.signature(&sig2)
.build(&mut assembly)?;
let ref3 = StandAloneSigBuilder::new()
.signature(&sig3)
.build(&mut assembly)?;
assert!(!Arc::ptr_eq(&ref1, &ref2));
assert!(!Arc::ptr_eq(&ref2, &ref3));
assert!(!Arc::ptr_eq(&ref1, &ref3));
Ok(())
}
}