use crate::{
cilassembly::{ChangeRefRc, CilAssembly},
metadata::{
tables::{EventMapRaw, TableDataOwned, TableId},
token::Token,
},
Error, Result,
};
#[derive(Debug, Clone)]
pub struct EventMapBuilder {
parent: Option<u32>,
event_list: Option<u32>,
}
impl Default for EventMapBuilder {
fn default() -> Self {
Self::new()
}
}
impl EventMapBuilder {
#[must_use]
pub fn new() -> Self {
Self {
parent: None,
event_list: None,
}
}
#[must_use]
pub fn parent(mut self, parent_row: u32) -> Self {
self.parent = Some(parent_row);
self
}
#[must_use]
pub fn event_list(mut self, event_list_index: u32) -> Self {
self.event_list = Some(event_list_index);
self
}
pub fn build(self, assembly: &mut CilAssembly) -> Result<ChangeRefRc> {
let parent_row = self.parent.ok_or_else(|| {
Error::ModificationInvalid("Parent row index is required for EventMap".to_string())
})?;
let event_list_index = self.event_list.ok_or_else(|| {
Error::ModificationInvalid("Event list index is required for EventMap".to_string())
})?;
if parent_row == 0 {
return Err(Error::ModificationInvalid(
"Parent row index cannot be 0".to_string(),
));
}
if event_list_index == 0 {
return Err(Error::ModificationInvalid(
"Event list index cannot be 0".to_string(),
));
}
let event_map = EventMapRaw {
rid: 0,
token: Token::new(0),
offset: 0,
parent: parent_row,
event_list: event_list_index,
};
assembly.table_row_add(TableId::EventMap, TableDataOwned::EventMap(event_map))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
cilassembly::ChangeRefKind, metadata::tables::TableId,
test::factories::table::assemblyref::get_test_assembly,
};
#[test]
fn test_event_map_builder_basic() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("EventfulClass")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let map_ref = EventMapBuilder::new()
.parent(type_ref.placeholder())
.event_list(1)
.build(&mut assembly)?;
assert_eq!(map_ref.kind(), ChangeRefKind::TableRow(TableId::EventMap));
Ok(())
}
#[test]
fn test_event_map_builder_default() -> Result<()> {
let builder = EventMapBuilder::default();
assert!(builder.parent.is_none());
assert!(builder.event_list.is_none());
Ok(())
}
#[test]
fn test_event_map_builder_missing_parent() -> Result<()> {
let mut assembly = get_test_assembly()?;
let result = EventMapBuilder::new().event_list(1).build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Parent row index is required"));
Ok(())
}
#[test]
fn test_event_map_builder_missing_event_list() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("EventfulClass")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let result = EventMapBuilder::new()
.parent(type_ref.placeholder())
.build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Event list index is required"));
Ok(())
}
#[test]
fn test_event_map_builder_zero_parent_row() -> Result<()> {
let mut assembly = get_test_assembly()?;
let result = EventMapBuilder::new()
.parent(0) .event_list(1)
.build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Parent row index cannot be 0"));
Ok(())
}
#[test]
fn test_event_map_builder_zero_event_list() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("EventfulClass")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let result = EventMapBuilder::new()
.parent(type_ref.placeholder())
.event_list(0) .build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Event list index cannot be 0"));
Ok(())
}
#[test]
fn test_event_map_builder_multiple_entries() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type1_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("EventfulClass1")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let type2_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("EventfulClass2")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let map1_ref = EventMapBuilder::new()
.parent(type1_ref.placeholder())
.event_list(1)
.build(&mut assembly)?;
let map2_ref = EventMapBuilder::new()
.parent(type2_ref.placeholder())
.event_list(3)
.build(&mut assembly)?;
assert!(!std::sync::Arc::ptr_eq(&map1_ref, &map2_ref));
assert_eq!(map1_ref.kind(), ChangeRefKind::TableRow(TableId::EventMap));
assert_eq!(map2_ref.kind(), ChangeRefKind::TableRow(TableId::EventMap));
Ok(())
}
#[test]
fn test_event_map_builder_various_event_indices() -> Result<()> {
let mut assembly = get_test_assembly()?;
let test_indices = [1, 5, 10, 20, 100];
for (i, &index) in test_indices.iter().enumerate() {
let type_ref = crate::metadata::tables::TypeDefBuilder::new()
.name(format!("EventfulClass{i}"))
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let map_ref = EventMapBuilder::new()
.parent(type_ref.placeholder())
.event_list(index)
.build(&mut assembly)?;
assert_eq!(map_ref.kind(), ChangeRefKind::TableRow(TableId::EventMap));
}
Ok(())
}
#[test]
fn test_event_map_builder_fluent_api() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_ref = crate::metadata::tables::TypeDefBuilder::new()
.name("FluentTestClass")
.namespace("MyApp")
.public_class()
.build(&mut assembly)?;
let map_ref = EventMapBuilder::new()
.parent(type_ref.placeholder())
.event_list(5)
.build(&mut assembly)?;
assert_eq!(map_ref.kind(), ChangeRefKind::TableRow(TableId::EventMap));
Ok(())
}
#[test]
fn test_event_map_builder_clone() {
let builder1 = EventMapBuilder::new().parent(1).event_list(1);
let builder2 = builder1.clone();
assert_eq!(builder1.parent, builder2.parent);
assert_eq!(builder1.event_list, builder2.event_list);
}
#[test]
fn test_event_map_builder_debug() {
let builder = EventMapBuilder::new().parent(1).event_list(1);
let debug_str = format!("{builder:?}");
assert!(debug_str.contains("EventMapBuilder"));
}
}