use crate::{
metadata::tables::{
fieldrva::FieldRvaRaw,
types::{RowWritable, TableId, TableInfoRef},
},
utils::{write_le_at, write_le_at_dyn},
Result,
};
impl RowWritable for FieldRvaRaw {
fn row_write(
&self,
data: &mut [u8],
offset: &mut usize,
_rid: u32,
sizes: &TableInfoRef,
) -> Result<()> {
write_le_at(data, offset, self.rva)?;
write_le_at_dyn(data, offset, self.field, sizes.is_large(TableId::Field))?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use crate::metadata::tables::{
fieldrva::FieldRvaRaw,
types::{RowReadable, RowWritable, TableId, TableInfo, TableRow},
};
use crate::metadata::token::Token;
#[test]
fn test_fieldrva_row_size() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let expected_size = 4 + 2; assert_eq!(<FieldRvaRaw as TableRow>::row_size(&sizes), expected_size);
let sizes_large = Arc::new(TableInfo::new_test(
&[(TableId::Field, 0x10000)],
false,
false,
false,
));
let expected_size_large = 4 + 4; assert_eq!(
<FieldRvaRaw as TableRow>::row_size(&sizes_large),
expected_size_large
);
}
#[test]
fn test_fieldrva_row_write_small() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let field_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: 0x01010101,
field: 0x0202,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, ];
assert_eq!(buffer, expected);
assert_eq!(offset, expected.len());
}
#[test]
fn test_fieldrva_row_write_large() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 0x10000)],
false,
false,
false,
));
let field_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: 0x01010101,
field: 0x02020202,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, ];
assert_eq!(buffer, expected);
assert_eq!(offset, expected.len());
}
#[test]
fn test_fieldrva_round_trip() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let original = FieldRvaRaw {
rid: 42,
token: Token::new(0x1D00002A),
offset: 0,
rva: 0x12345678, field: 25, };
let mut buffer = vec![0u8; <FieldRvaRaw 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 = FieldRvaRaw::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.rva, read_back.rva);
assert_eq!(original.field, read_back.field);
}
#[test]
fn test_fieldrva_different_rvas() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let test_cases = vec![
(0x00001000, 1), (0x00002000, 2), (0x00004000, 3), (0x12345678, 4), (0xABCDEF00, 5), (0x00000400, 6), (0xFFFFFFFF, 7), (0x00000000, 8), ];
for (rva_value, field_index) in test_cases {
let field_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: rva_value,
field: field_index,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let mut read_offset = 0;
let read_back = FieldRvaRaw::row_read(&buffer, &mut read_offset, 1, &sizes).unwrap();
assert_eq!(field_rva.rva, read_back.rva);
assert_eq!(field_rva.field, read_back.field);
}
}
#[test]
fn test_fieldrva_edge_cases() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let zero_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: 0,
field: 0,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
zero_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ];
assert_eq!(buffer, expected);
let max_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: 0xFFFFFFFF,
field: 0xFFFF,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
max_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
assert_eq!(buffer.len(), 6); }
#[test]
fn test_fieldrva_section_alignment() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let alignment_cases = vec![
(0x00001000, 1), (0x00002000, 2), (0x00004000, 3), (0x00008000, 4), (0x00010000, 5), (0x00020000, 6), (0x00040000, 7), (0x00080000, 8), ];
for (aligned_rva, field_index) in alignment_cases {
let field_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: aligned_rva,
field: field_index,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let written_rva = u32::from_le_bytes([buffer[0], buffer[1], buffer[2], buffer[3]]);
assert_eq!(written_rva, aligned_rva);
let written_field = u16::from_le_bytes([buffer[4], buffer[5]]);
assert_eq!(written_field as u32, field_index);
}
}
#[test]
fn test_fieldrva_pe_context() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::Field, 100)],
false,
false,
false,
));
let pe_scenarios = vec![
(0x00001000, 1, "Code section start"),
(0x00002000, 2, "Data section start"),
(0x00003000, 3, "Resources section start"),
(0x00004000, 4, "Import table location"),
(0x00005000, 5, "Export table location"),
(0x00010000, 6, "Large data array"),
(0x00020000, 7, "Embedded resource"),
(0x00040000, 8, "Debug information"),
];
for (rva, field_index, _description) in pe_scenarios {
let field_rva = FieldRvaRaw {
rid: field_index,
token: Token::new(0x1D000000 + field_index),
offset: 0,
rva,
field: field_index,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, field_index, &sizes)
.unwrap();
let mut read_offset = 0;
let read_back =
FieldRvaRaw::row_read(&buffer, &mut read_offset, field_index, &sizes).unwrap();
assert_eq!(field_rva.rva, read_back.rva);
assert_eq!(field_rva.field, read_back.field);
}
}
#[test]
fn test_fieldrva_known_binary_format() {
let sizes = Arc::new(TableInfo::new_test(
&[(TableId::FieldRVA, 1), (TableId::Field, 10)],
false,
false,
false,
));
let field_rva = FieldRvaRaw {
rid: 1,
token: Token::new(0x1D000001),
offset: 0,
rva: 0x01010101,
field: 0x0202,
};
let mut buffer = vec![0u8; <FieldRvaRaw as TableRow>::row_size(&sizes) as usize];
let mut offset = 0;
field_rva
.row_write(&mut buffer, &mut offset, 1, &sizes)
.unwrap();
let expected = vec![
0x01, 0x01, 0x01, 0x01, 0x02, 0x02, ];
assert_eq!(buffer, expected);
}
}