use crate::{
cilassembly::{ChangeRefRc, CilAssembly},
metadata::{
tables::{PropertyMapRaw, TableDataOwned, TableId},
token::Token,
},
Error, Result,
};
#[derive(Debug, Clone)]
pub struct PropertyMapBuilder {
parent: Option<u32>,
property_list: Option<u32>,
}
impl Default for PropertyMapBuilder {
fn default() -> Self {
Self::new()
}
}
impl PropertyMapBuilder {
#[must_use]
pub fn new() -> Self {
Self {
parent: None,
property_list: None,
}
}
#[must_use]
pub fn parent(mut self, parent_row: u32) -> Self {
self.parent = Some(parent_row);
self
}
#[must_use]
pub fn property_list(mut self, property_list_index: u32) -> Self {
self.property_list = Some(property_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 PropertyMap".to_string())
})?;
let property_list_index = self.property_list.ok_or_else(|| {
Error::ModificationInvalid(
"Property list index is required for PropertyMap".to_string(),
)
})?;
if parent_row == 0 {
return Err(Error::ModificationInvalid(
"Parent row index cannot be 0".to_string(),
));
}
if property_list_index == 0 {
return Err(Error::ModificationInvalid(
"Property list index cannot be 0".to_string(),
));
}
let property_map = PropertyMapRaw {
rid: 0,
token: Token::new(0),
offset: 0,
parent: parent_row,
property_list: property_list_index,
};
assembly.table_row_add(
TableId::PropertyMap,
TableDataOwned::PropertyMap(property_map),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test::factories::table::assemblyref::get_test_assembly;
use std::sync::Arc;
#[test]
fn test_property_map_builder_basic() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_row = 1u32;
let _change_ref = PropertyMapBuilder::new()
.parent(type_row)
.property_list(1)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_property_map_builder_default() -> Result<()> {
let builder = PropertyMapBuilder::default();
assert!(builder.parent.is_none());
assert!(builder.property_list.is_none());
Ok(())
}
#[test]
fn test_property_map_builder_missing_parent() -> Result<()> {
let mut assembly = get_test_assembly()?;
let result = PropertyMapBuilder::new()
.property_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_property_map_builder_missing_property_list() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_row = 1u32;
let result = PropertyMapBuilder::new()
.parent(type_row)
.build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Property list index is required"));
Ok(())
}
#[test]
fn test_property_map_builder_zero_row_parent() -> Result<()> {
let mut assembly = get_test_assembly()?;
let zero_row = 0u32;
let result = PropertyMapBuilder::new()
.parent(zero_row)
.property_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_property_map_builder_zero_property_list() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_row = 1u32;
let result = PropertyMapBuilder::new()
.parent(type_row)
.property_list(0) .build(&mut assembly);
assert!(result.is_err());
let error_msg = result.unwrap_err().to_string();
assert!(error_msg.contains("Property list index cannot be 0"));
Ok(())
}
#[test]
fn test_property_map_builder_multiple_entries() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type1_row = 1u32;
let type2_row = 2u32;
let ref1 = PropertyMapBuilder::new()
.parent(type1_row)
.property_list(1)
.build(&mut assembly)?;
let ref2 = PropertyMapBuilder::new()
.parent(type2_row)
.property_list(3)
.build(&mut assembly)?;
assert!(!Arc::ptr_eq(&ref1, &ref2));
Ok(())
}
#[test]
fn test_property_map_builder_various_property_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_row = 1u32 + i as u32;
let _change_ref = PropertyMapBuilder::new()
.parent(type_row)
.property_list(index)
.build(&mut assembly)?;
}
Ok(())
}
#[test]
fn test_property_map_builder_fluent_api() -> Result<()> {
let mut assembly = get_test_assembly()?;
let type_row = 1u32;
let _change_ref = PropertyMapBuilder::new()
.parent(type_row)
.property_list(5)
.build(&mut assembly)?;
Ok(())
}
#[test]
fn test_property_map_builder_clone() {
let parent_row = 1u32;
let builder1 = PropertyMapBuilder::new()
.parent(parent_row)
.property_list(1);
let builder2 = builder1.clone();
assert_eq!(builder1.parent, builder2.parent);
assert_eq!(builder1.property_list, builder2.property_list);
}
#[test]
fn test_property_map_builder_debug() {
let parent_row = 1u32;
let builder = PropertyMapBuilder::new()
.parent(parent_row)
.property_list(1);
let debug_str = format!("{builder:?}");
assert!(debug_str.contains("PropertyMapBuilder"));
}
}