use crate::{
cilassembly::{ChangeRefRc, CilAssembly},
metadata::{
sequencepoints::SequencePoints,
tables::{MethodDebugInformationRaw, TableDataOwned, TableId},
token::Token,
},
Result,
};
#[derive(Debug, Clone)]
pub struct MethodDebugInformationBuilder {
document: Option<u32>,
sequence_points: Option<Vec<u8>>,
}
impl Default for MethodDebugInformationBuilder {
fn default() -> Self {
Self::new()
}
}
impl MethodDebugInformationBuilder {
#[must_use]
pub fn new() -> Self {
Self {
document: None,
sequence_points: None,
}
}
#[must_use]
pub fn document(mut self, document_index: u32) -> Self {
self.document = Some(document_index);
self
}
#[must_use]
pub fn sequence_points(mut self, data: Vec<u8>) -> Self {
self.sequence_points = Some(data);
self
}
#[must_use]
pub fn sequence_points_parsed(mut self, points: &SequencePoints) -> Self {
self.sequence_points = Some(points.to_bytes());
self
}
pub fn build(self, assembly: &mut CilAssembly) -> Result<ChangeRefRc> {
let document_index = self.document.unwrap_or(0);
let sequence_points_index = if let Some(data) = self.sequence_points {
if data.is_empty() {
0
} else {
assembly.blob_add(&data)?.placeholder()
}
} else {
0
};
let method_debug_info = MethodDebugInformationRaw {
rid: 0,
token: Token::new(0),
offset: 0,
document: document_index,
sequence_points: sequence_points_index,
};
assembly.table_row_add(
TableId::MethodDebugInformation,
TableDataOwned::MethodDebugInformation(method_debug_info),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
cilassembly::ChangeRefKind, metadata::tables::TableId,
test::factories::table::assemblyref::get_test_assembly,
};
#[test]
fn test_method_debug_information_builder_basic() -> Result<()> {
let mut assembly = get_test_assembly()?;
let ref_ = MethodDebugInformationBuilder::new()
.document(1)
.sequence_points(vec![0x01, 0x02, 0x03])
.build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
#[test]
fn test_method_debug_information_builder_default() -> Result<()> {
let builder = MethodDebugInformationBuilder::default();
assert!(builder.document.is_none());
assert!(builder.sequence_points.is_none());
Ok(())
}
#[test]
fn test_method_debug_information_builder_minimal() -> Result<()> {
let mut assembly = get_test_assembly()?;
let ref_ = MethodDebugInformationBuilder::new().build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
#[test]
fn test_method_debug_information_builder_document_only() -> Result<()> {
let mut assembly = get_test_assembly()?;
let ref_ = MethodDebugInformationBuilder::new()
.document(5)
.build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
#[test]
fn test_method_debug_information_builder_sequence_points_only() -> Result<()> {
let mut assembly = get_test_assembly()?;
let sequence_data = vec![0x10, 0x20, 0x30, 0x40];
let ref_ = MethodDebugInformationBuilder::new()
.sequence_points(sequence_data)
.build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
#[test]
fn test_method_debug_information_builder_empty_sequence_points() -> Result<()> {
let mut assembly = get_test_assembly()?;
let ref_ = MethodDebugInformationBuilder::new()
.document(1)
.sequence_points(vec![])
.build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
#[test]
fn test_method_debug_information_builder_fluent_api() -> Result<()> {
let mut assembly = get_test_assembly()?;
let ref_ = MethodDebugInformationBuilder::new()
.document(3)
.sequence_points(vec![0xAA, 0xBB, 0xCC])
.build(&mut assembly)?;
assert_eq!(
ref_.kind(),
ChangeRefKind::TableRow(TableId::MethodDebugInformation)
);
Ok(())
}
}