use crate::{
metadata::tables::{
memberref::MemberRefRaw,
types::{CodedIndexType, RowWritable, TableInfoRef},
},
utils::write_le_at_dyn,
Result,
};
impl RowWritable for MemberRefRaw {
fn row_write(
&self,
data: &mut [u8],
offset: &mut usize,
_rid: u32,
sizes: &TableInfoRef,
) -> Result<()> {
let class_value = sizes.encode_coded_index(
self.class.tag,
self.class.row,
CodedIndexType::MemberRefParent,
)?;
write_le_at_dyn(
data,
offset,
class_value,
sizes.coded_index_bits(CodedIndexType::MemberRefParent) > 16,
)?;
write_le_at_dyn(data, offset, self.name, sizes.is_large_str())?;
write_le_at_dyn(data, offset, self.signature, sizes.is_large_blob())?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use crate::metadata::tables::{
memberref::MemberRefRaw,
types::{
CodedIndex, CodedIndexType, RowReadable, RowWritable, TableId, TableInfo, TableRow,
},
};
use crate::metadata::token::Token;
#[test]
fn test_memberref_row_size() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
false,
false,
false,
));
let expected_size = 2 + 2 + 2; assert_eq!(<MemberRefRaw as TableRow>::row_size(&sizes), expected_size);
let sizes_large = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
true,
true,
true,
));
let expected_size_large = 2 + 4 + 4; assert_eq!(
<MemberRefRaw as TableRow>::row_size(&sizes_large),
expected_size_large
);
}
#[test]
fn test_memberref_row_write_small_heaps() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
false,
false,
false,
));
let member_ref = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(TableId::TypeRef, 42, CodedIndexType::MemberRefParent), name: 0x1234,
signature: 0x5678,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
member_ref
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x51, 0x01, 0x34, 0x12, 0x78, 0x56, ];
assert_eq!(buffer, expected);
assert_eq!(offset, expected.len());
}
#[test]
fn test_memberref_row_write_large_heaps() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
true,
true,
true,
));
let member_ref = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(TableId::TypeRef, 1000, CodedIndexType::MemberRefParent), name: 0x12345678,
signature: 0xABCDEF01,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
member_ref
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x41, 0x1F, 0x78, 0x56, 0x34, 0x12, 0x01, 0xEF, 0xCD, 0xAB, ];
assert_eq!(buffer, expected);
assert_eq!(offset, expected.len());
}
#[test]
fn test_memberref_round_trip_small() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
false,
false,
false,
));
let original = MemberRefRaw {
rid: 42,
token: Token::new(0x0A00002A),
offset: 0,
class: CodedIndex::new(TableId::TypeDef, 15, CodedIndexType::MemberRefParent),
name: 0x00AA,
signature: 0x00BB,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
original
.row_write(&mut buffer, &mut offset, 42, &sizes)
.unwrap();
let mut read_offset = 0;
let read_back = MemberRefRaw::row_read(&buffer, &mut read_offset, 42, &sizes).unwrap();
assert_eq!(original.rid, read_back.rid);
assert_eq!(original.token, read_back.token);
assert_eq!(original.class, read_back.class);
assert_eq!(original.name, read_back.name);
assert_eq!(original.signature, read_back.signature);
}
#[test]
fn test_memberref_edge_cases() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
false,
false,
false,
));
let zero_member = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(TableId::TypeDef, 0, CodedIndexType::MemberRefParent),
name: 0,
signature: 0,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
zero_member
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
assert_eq!(buffer, vec![0; buffer.len()]);
let max_member = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(TableId::TypeDef, 0x1FFF, CodedIndexType::MemberRefParent), name: 0xFFFF,
signature: 0xFFFF,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
max_member
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
assert_eq!(buffer.len(), 6); }
#[test]
fn test_memberref_different_coded_index_types() {
let sizes = Arc::new(TableInfo::new_test(
&[
(TableId::TypeDef, 100),
(TableId::TypeRef, 50),
(TableId::ModuleRef, 10),
],
false,
false,
false,
));
let typedef_ref = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(TableId::TypeDef, 10, CodedIndexType::MemberRefParent),
name: 0x1000,
signature: 0x2000,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
typedef_ref
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
assert_eq!(buffer[0], 0x50);
assert_eq!(buffer[1], 0x00);
let typeref_ref = MemberRefRaw {
rid: 2,
token: Token::new(0x0A000002),
offset: 0,
class: CodedIndex::new(TableId::TypeRef, 10, CodedIndexType::MemberRefParent),
name: 0x1000,
signature: 0x2000,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
typeref_ref
.row_write(&mut buffer, &mut offset, 2, &sizes)
.unwrap();
assert_eq!(buffer[0], 0x51);
assert_eq!(buffer[1], 0x00);
}
#[test]
fn test_memberref_known_binary_format() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::MethodDef, 1)],
false,
false,
false,
));
let member_ref = MemberRefRaw {
rid: 1,
token: Token::new(0x0A000001),
offset: 0,
class: CodedIndex::new(
TableId::TypeRef,
0x0101 >> 3,
CodedIndexType::MemberRefParent,
), name: 0x0202,
signature: 0x0303,
};
let mut buffer = vec![0u8; <MemberRefRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
member_ref
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x01, 0x01, 0x02, 0x02, 0x03, 0x03, ];
assert_eq!(buffer, expected);
}
}