Expose save-side placed-structure triplets
This commit is contained in:
parent
e01039379b
commit
5928815465
1 changed files with 266 additions and 0 deletions
|
|
@ -1701,6 +1701,39 @@ pub struct SmpSaveRegionRecordTripletProbe {
|
||||||
pub evidence: Vec<String>,
|
pub evidence: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureRecordTripletEntryProbe {
|
||||||
|
pub record_index: usize,
|
||||||
|
pub primary_name: String,
|
||||||
|
pub secondary_name: String,
|
||||||
|
pub name_tag_relative_offset: usize,
|
||||||
|
pub policy_tag_relative_offset: usize,
|
||||||
|
pub profile_tag_relative_offset: usize,
|
||||||
|
pub policy_chunk_len: usize,
|
||||||
|
pub profile_chunk_len: usize,
|
||||||
|
pub policy_f32_lane_0: f32,
|
||||||
|
pub policy_f32_lane_1: f32,
|
||||||
|
pub policy_f32_lane_2: f32,
|
||||||
|
pub policy_f32_lane_3: f32,
|
||||||
|
pub policy_f32_lane_4: f32,
|
||||||
|
pub policy_reserved_dword: u32,
|
||||||
|
pub policy_trailing_word: u16,
|
||||||
|
pub policy_trailing_word_hex: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct SmpSavePlacedStructureRecordTripletProbe {
|
||||||
|
pub profile_family: String,
|
||||||
|
pub source_kind: String,
|
||||||
|
pub semantic_family: String,
|
||||||
|
pub records_tag_offset: usize,
|
||||||
|
pub close_tag_offset: usize,
|
||||||
|
pub record_count: usize,
|
||||||
|
#[serde(default)]
|
||||||
|
pub entries: Vec<SmpSavePlacedStructureRecordTripletEntryProbe>,
|
||||||
|
pub evidence: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct SmpRt3105SaveNameTableProbe {
|
pub struct SmpRt3105SaveNameTableProbe {
|
||||||
pub profile_family: String,
|
pub profile_family: String,
|
||||||
|
|
@ -2645,6 +2678,8 @@ pub struct SmpSaveCompanyChairmanAnalysisReport {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub placed_structure_collection_header: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
pub placed_structure_collection_header: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub placed_structure_record_triplets: Option<SmpSavePlacedStructureRecordTripletProbe>,
|
||||||
|
#[serde(default)]
|
||||||
pub company_entries: Vec<SmpSaveCompanyRecordAnalysisEntry>,
|
pub company_entries: Vec<SmpSaveCompanyRecordAnalysisEntry>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub chairman_entries: Vec<SmpSaveChairmanRecordAnalysisEntry>,
|
pub chairman_entries: Vec<SmpSaveChairmanRecordAnalysisEntry>,
|
||||||
|
|
@ -2908,6 +2943,8 @@ pub struct SmpInspectionReport {
|
||||||
pub save_region_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
pub save_region_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
||||||
pub save_region_record_triplet_probe: Option<SmpSaveRegionRecordTripletProbe>,
|
pub save_region_record_triplet_probe: Option<SmpSaveRegionRecordTripletProbe>,
|
||||||
pub save_placed_structure_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
pub save_placed_structure_collection_header_probe: Option<SmpSaveTaggedCollectionHeaderProbe>,
|
||||||
|
pub save_placed_structure_record_triplet_probe:
|
||||||
|
Option<SmpSavePlacedStructureRecordTripletProbe>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub save_company_roster_probe: Option<SmpLoadedCompanyRoster>,
|
pub save_company_roster_probe: Option<SmpLoadedCompanyRoster>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|
@ -3239,6 +3276,19 @@ pub fn load_save_slice_from_report(
|
||||||
probe.close_tag_offset
|
probe.close_tag_offset
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(probe) = &report.save_placed_structure_record_triplet_probe {
|
||||||
|
notes.push(format!(
|
||||||
|
"Raw save tagged placed-structure records also expose {} repeated 0x55f1/0x55f2/0x55f3 triplets; first stems={:?}/{:?}, first policy lanes=({:.3}, {:.3}, {:.3}, {:.3}, {:.3}).",
|
||||||
|
probe.record_count,
|
||||||
|
probe.entries.first().map(|entry| entry.primary_name.as_str()),
|
||||||
|
probe.entries.first().map(|entry| entry.secondary_name.as_str()),
|
||||||
|
probe.entries.first().map(|entry| entry.policy_f32_lane_0).unwrap_or_default(),
|
||||||
|
probe.entries.first().map(|entry| entry.policy_f32_lane_1).unwrap_or_default(),
|
||||||
|
probe.entries.first().map(|entry| entry.policy_f32_lane_2).unwrap_or_default(),
|
||||||
|
probe.entries.first().map(|entry| entry.policy_f32_lane_3).unwrap_or_default(),
|
||||||
|
probe.entries.first().map(|entry| entry.policy_f32_lane_4).unwrap_or_default()
|
||||||
|
));
|
||||||
|
}
|
||||||
if let Some(roster) = &report.save_company_roster_probe {
|
if let Some(roster) = &report.save_company_roster_probe {
|
||||||
notes.push(format!(
|
notes.push(format!(
|
||||||
"Raw save inspection reconstructed {} company direct records from the tagged company collection.",
|
"Raw save inspection reconstructed {} company direct records from the tagged company collection.",
|
||||||
|
|
@ -3301,6 +3351,8 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
let world_finance_neighborhood = report.save_world_finance_neighborhood_probe.clone();
|
let world_finance_neighborhood = report.save_world_finance_neighborhood_probe.clone();
|
||||||
let train_collection_directory = report.save_train_collection_directory_probe.clone();
|
let train_collection_directory = report.save_train_collection_directory_probe.clone();
|
||||||
let region_record_triplets = report.save_region_record_triplet_probe.clone();
|
let region_record_triplets = report.save_region_record_triplet_probe.clone();
|
||||||
|
let placed_structure_record_triplets =
|
||||||
|
report.save_placed_structure_record_triplet_probe.clone();
|
||||||
let company_header_probe = report.save_company_collection_header_probe.as_ref();
|
let company_header_probe = report.save_company_collection_header_probe.as_ref();
|
||||||
let chairman_header_probe = report
|
let chairman_header_probe = report
|
||||||
.save_chairman_profile_collection_header_probe
|
.save_chairman_profile_collection_header_probe
|
||||||
|
|
@ -3645,6 +3697,14 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
header.live_record_count, header.live_id_bound, header.direct_record_stride
|
header.live_record_count, header.live_id_bound, header.direct_record_stride
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
if let Some(triplets) = placed_structure_record_triplets.as_ref() {
|
||||||
|
notes.push(format!(
|
||||||
|
"Placed-structure analysis now also exports {} tagged 0x55f1/0x55f2/0x55f3 record triplets; first stems={:?}/{:?}.",
|
||||||
|
triplets.record_count,
|
||||||
|
triplets.entries.first().map(|entry| entry.primary_name.as_str()),
|
||||||
|
triplets.entries.first().map(|entry| entry.secondary_name.as_str())
|
||||||
|
));
|
||||||
|
}
|
||||||
if !company_entries.is_empty() {
|
if !company_entries.is_empty() {
|
||||||
notes.push(
|
notes.push(
|
||||||
"Company debt is derived from the grounded bond table at [company+0x5b/+0x5f] by summing live principal slots.".to_string(),
|
"Company debt is derived from the grounded bond table at [company+0x5b/+0x5f] by summing live principal slots.".to_string(),
|
||||||
|
|
@ -3693,6 +3753,7 @@ pub fn inspect_save_company_and_chairman_analysis_bytes(
|
||||||
placed_structure_collection_header: report
|
placed_structure_collection_header: report
|
||||||
.save_placed_structure_collection_header_probe
|
.save_placed_structure_collection_header_probe
|
||||||
.clone(),
|
.clone(),
|
||||||
|
placed_structure_record_triplets,
|
||||||
company_entries,
|
company_entries,
|
||||||
chairman_entries,
|
chairman_entries,
|
||||||
notes,
|
notes,
|
||||||
|
|
@ -7713,6 +7774,11 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option<String>) -> Sm
|
||||||
file_extension_hint.as_deref(),
|
file_extension_hint.as_deref(),
|
||||||
container_profile.as_ref(),
|
container_profile.as_ref(),
|
||||||
);
|
);
|
||||||
|
let save_placed_structure_record_triplet_probe =
|
||||||
|
parse_save_placed_structure_record_triplet_probe(
|
||||||
|
bytes,
|
||||||
|
save_placed_structure_collection_header_probe.as_ref(),
|
||||||
|
);
|
||||||
let save_company_roster_probe = parse_save_company_roster_probe(
|
let save_company_roster_probe = parse_save_company_roster_probe(
|
||||||
bytes,
|
bytes,
|
||||||
save_company_collection_header_probe.as_ref(),
|
save_company_collection_header_probe.as_ref(),
|
||||||
|
|
@ -7881,6 +7947,7 @@ fn inspect_bundle_bytes(bytes: &[u8], file_extension_hint: Option<String>) -> Sm
|
||||||
save_region_collection_header_probe,
|
save_region_collection_header_probe,
|
||||||
save_region_record_triplet_probe,
|
save_region_record_triplet_probe,
|
||||||
save_placed_structure_collection_header_probe,
|
save_placed_structure_collection_header_probe,
|
||||||
|
save_placed_structure_record_triplet_probe,
|
||||||
save_company_roster_probe,
|
save_company_roster_probe,
|
||||||
save_chairman_profile_table_probe,
|
save_chairman_profile_table_probe,
|
||||||
rt3_105_save_name_table_probe,
|
rt3_105_save_name_table_probe,
|
||||||
|
|
@ -10060,6 +10127,95 @@ fn parse_save_region_record_triplet_probe(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_save_placed_structure_record_triplet_probe(
|
||||||
|
bytes: &[u8],
|
||||||
|
header_probe: Option<&SmpSaveTaggedCollectionHeaderProbe>,
|
||||||
|
) -> Option<SmpSavePlacedStructureRecordTripletProbe> {
|
||||||
|
let header_probe = header_probe?;
|
||||||
|
if header_probe.source_kind != "save-placed-structure-tagged-header-counts" {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let records_payload =
|
||||||
|
bytes.get(header_probe.records_tag_offset + 4..header_probe.close_tag_offset)?;
|
||||||
|
let name_offsets = find_u16_le_offsets(records_payload, SAVE_REGION_RECORD_NAME_TAG);
|
||||||
|
let policy_offsets = find_u16_le_offsets(records_payload, SAVE_REGION_RECORD_POLICY_TAG);
|
||||||
|
let profile_offsets = find_u16_le_offsets(records_payload, SAVE_REGION_RECORD_PROFILE_TAG);
|
||||||
|
let record_count = header_probe.live_record_count as usize;
|
||||||
|
if name_offsets.len() != record_count
|
||||||
|
|| policy_offsets.len() != record_count
|
||||||
|
|| profile_offsets.len() != record_count
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut entries = Vec::with_capacity(record_count);
|
||||||
|
for index in 0..record_count {
|
||||||
|
let name_tag_relative_offset = name_offsets[index];
|
||||||
|
let policy_tag_relative_offset = policy_offsets[index];
|
||||||
|
let profile_tag_relative_offset = profile_offsets[index];
|
||||||
|
let next_record_relative_offset = name_offsets
|
||||||
|
.get(index + 1)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(records_payload.len());
|
||||||
|
if !(name_tag_relative_offset < policy_tag_relative_offset
|
||||||
|
&& policy_tag_relative_offset < profile_tag_relative_offset
|
||||||
|
&& profile_tag_relative_offset < next_record_relative_offset)
|
||||||
|
{
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let name_payload =
|
||||||
|
records_payload.get(name_tag_relative_offset + 4..policy_tag_relative_offset)?;
|
||||||
|
let (primary_name, secondary_name) = parse_save_len_prefixed_ascii_name_pair(name_payload)?;
|
||||||
|
let policy_chunk_len =
|
||||||
|
profile_tag_relative_offset.checked_sub(policy_tag_relative_offset + 4)?;
|
||||||
|
if policy_chunk_len != 0x1a {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let policy_payload =
|
||||||
|
records_payload.get(policy_tag_relative_offset + 4..profile_tag_relative_offset)?;
|
||||||
|
let policy_f32_lane_0 = f32::from_bits(read_u32_at(policy_payload, 0)?);
|
||||||
|
let policy_f32_lane_1 = f32::from_bits(read_u32_at(policy_payload, 4)?);
|
||||||
|
let policy_f32_lane_2 = f32::from_bits(read_u32_at(policy_payload, 8)?);
|
||||||
|
let policy_f32_lane_3 = f32::from_bits(read_u32_at(policy_payload, 12)?);
|
||||||
|
let policy_f32_lane_4 = f32::from_bits(read_u32_at(policy_payload, 16)?);
|
||||||
|
let policy_reserved_dword = read_u32_at(policy_payload, 20)?;
|
||||||
|
let policy_trailing_word = read_u16_at(policy_payload, 24)?;
|
||||||
|
let profile_chunk_len =
|
||||||
|
next_record_relative_offset.checked_sub(profile_tag_relative_offset + 4)?;
|
||||||
|
entries.push(SmpSavePlacedStructureRecordTripletEntryProbe {
|
||||||
|
record_index: index,
|
||||||
|
primary_name,
|
||||||
|
secondary_name,
|
||||||
|
name_tag_relative_offset,
|
||||||
|
policy_tag_relative_offset,
|
||||||
|
profile_tag_relative_offset,
|
||||||
|
policy_chunk_len,
|
||||||
|
profile_chunk_len,
|
||||||
|
policy_f32_lane_0,
|
||||||
|
policy_f32_lane_1,
|
||||||
|
policy_f32_lane_2,
|
||||||
|
policy_f32_lane_3,
|
||||||
|
policy_f32_lane_4,
|
||||||
|
policy_reserved_dword,
|
||||||
|
policy_trailing_word,
|
||||||
|
policy_trailing_word_hex: format!("0x{policy_trailing_word:04x}"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Some(SmpSavePlacedStructureRecordTripletProbe {
|
||||||
|
profile_family: header_probe.profile_family.clone(),
|
||||||
|
source_kind: "save-placed-structure-record-triplets".to_string(),
|
||||||
|
semantic_family: "scenario-save-placed-structure-record-triplets".to_string(),
|
||||||
|
records_tag_offset: header_probe.records_tag_offset,
|
||||||
|
close_tag_offset: header_probe.close_tag_offset,
|
||||||
|
record_count,
|
||||||
|
entries,
|
||||||
|
evidence: vec![
|
||||||
|
"save-side placed-structure records are serialized as repeated 0x55f1/0x55f2/0x55f3 triplets inside the tagged records span".to_string(),
|
||||||
|
"the 0x55f1 chunk currently exposes two len-prefixed structure-name stems before the fixed 0x55f2 policy row".to_string(),
|
||||||
|
"each fixed placed-structure 0x55f2 policy chunk currently decodes as five f32-like lanes, one reserved dword, and one trailing u16 word".to_string(),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_save_placed_structure_collection_header_probe(
|
fn parse_save_placed_structure_collection_header_probe(
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
file_extension_hint: Option<&str>,
|
file_extension_hint: Option<&str>,
|
||||||
|
|
@ -10210,6 +10366,29 @@ fn parse_save_len_prefixed_ascii_name(bytes: &[u8]) -> Option<String> {
|
||||||
Some(text.to_string())
|
Some(text.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_save_len_prefixed_ascii_name_pair(bytes: &[u8]) -> Option<(String, String)> {
|
||||||
|
let first_len = *bytes.first()? as usize;
|
||||||
|
let first_end = 1 + first_len;
|
||||||
|
let first = std::str::from_utf8(bytes.get(1..first_end)?)
|
||||||
|
.ok()?
|
||||||
|
.trim_end_matches('\0')
|
||||||
|
.to_string();
|
||||||
|
let mut second_len_offset = first_end;
|
||||||
|
while matches!(bytes.get(second_len_offset), Some(0)) {
|
||||||
|
second_len_offset += 1;
|
||||||
|
}
|
||||||
|
let second_len = *bytes.get(second_len_offset)? as usize;
|
||||||
|
let second_start = second_len_offset + 1;
|
||||||
|
let second = std::str::from_utf8(bytes.get(second_start..second_start + second_len)?)
|
||||||
|
.ok()?
|
||||||
|
.trim_end_matches('\0')
|
||||||
|
.to_string();
|
||||||
|
if first.is_empty() || second.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some((first, second))
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_save_fixed_ascii_name(bytes: &[u8]) -> Option<String> {
|
fn parse_save_fixed_ascii_name(bytes: &[u8]) -> Option<String> {
|
||||||
let nul_index = bytes
|
let nul_index = bytes
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -17626,6 +17805,93 @@ mod tests {
|
||||||
assert_eq!(profile_probe.entries[1].trailing_weight_f32, 0.45);
|
assert_eq!(profile_probe.entries[1].trailing_weight_f32, 0.45);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parses_placed_structure_record_triplet_probe_from_dual_name_rows() {
|
||||||
|
let mut bytes = vec![0u8; 0x400];
|
||||||
|
let metadata_tag_offset = 0x40usize;
|
||||||
|
let records_tag_offset = 0x140usize;
|
||||||
|
let close_tag_offset = 0x260usize;
|
||||||
|
bytes[metadata_tag_offset..metadata_tag_offset + 4]
|
||||||
|
.copy_from_slice(&0x000036b1u32.to_le_bytes());
|
||||||
|
bytes[records_tag_offset..records_tag_offset + 4]
|
||||||
|
.copy_from_slice(&0x000036b2u32.to_le_bytes());
|
||||||
|
bytes[close_tag_offset..close_tag_offset + 4].copy_from_slice(&0x000036b3u32.to_le_bytes());
|
||||||
|
let mut cursor = records_tag_offset + 4;
|
||||||
|
for (primary, secondary, lane0, lane1, lane2, lane3, lane4) in [
|
||||||
|
(
|
||||||
|
"StationA",
|
||||||
|
"StationSetA",
|
||||||
|
43111.92f32,
|
||||||
|
1385.5f32,
|
||||||
|
34581.95f32,
|
||||||
|
0.0f32,
|
||||||
|
5.9760494f32,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"StationB",
|
||||||
|
"StationSetB",
|
||||||
|
44000.0f32,
|
||||||
|
1200.0f32,
|
||||||
|
33000.0f32,
|
||||||
|
0.0f32,
|
||||||
|
4.5f32,
|
||||||
|
),
|
||||||
|
] {
|
||||||
|
bytes[cursor..cursor + 2].copy_from_slice(&SAVE_REGION_RECORD_NAME_TAG.to_le_bytes());
|
||||||
|
bytes[cursor + 4] = primary.len() as u8;
|
||||||
|
bytes[cursor + 5..cursor + 5 + primary.len()].copy_from_slice(primary.as_bytes());
|
||||||
|
let second_len_offset = cursor + 5 + primary.len();
|
||||||
|
bytes[second_len_offset] = secondary.len() as u8;
|
||||||
|
bytes[second_len_offset + 1..second_len_offset + 1 + secondary.len()]
|
||||||
|
.copy_from_slice(secondary.as_bytes());
|
||||||
|
cursor += 0x19;
|
||||||
|
bytes[cursor..cursor + 2].copy_from_slice(&SAVE_REGION_RECORD_POLICY_TAG.to_le_bytes());
|
||||||
|
bytes[cursor + 4..cursor + 8].copy_from_slice(&lane0.to_bits().to_le_bytes());
|
||||||
|
bytes[cursor + 8..cursor + 12].copy_from_slice(&lane1.to_bits().to_le_bytes());
|
||||||
|
bytes[cursor + 12..cursor + 16].copy_from_slice(&lane2.to_bits().to_le_bytes());
|
||||||
|
bytes[cursor + 16..cursor + 20].copy_from_slice(&lane3.to_bits().to_le_bytes());
|
||||||
|
bytes[cursor + 20..cursor + 24].copy_from_slice(&lane4.to_bits().to_le_bytes());
|
||||||
|
bytes[cursor + 28..cursor + 30].copy_from_slice(&0x0101u16.to_le_bytes());
|
||||||
|
cursor += 0x1e;
|
||||||
|
bytes[cursor..cursor + 2]
|
||||||
|
.copy_from_slice(&SAVE_REGION_RECORD_PROFILE_TAG.to_le_bytes());
|
||||||
|
cursor += 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
let header_probe = SmpSaveTaggedCollectionHeaderProbe {
|
||||||
|
profile_family: "rt3-105-save-container-v1".to_string(),
|
||||||
|
source_kind: "save-placed-structure-tagged-header-counts".to_string(),
|
||||||
|
semantic_family: "scenario-save-placed-structure-header-counts".to_string(),
|
||||||
|
metadata_tag_offset,
|
||||||
|
records_tag_offset,
|
||||||
|
close_tag_offset,
|
||||||
|
direct_collection_flag: 0,
|
||||||
|
direct_collection_flag_hex: "0x00000000".to_string(),
|
||||||
|
direct_record_stride: 0x06,
|
||||||
|
direct_record_stride_hex: "0x00000006".to_string(),
|
||||||
|
live_id_bound: 3,
|
||||||
|
live_id_bound_hex: "0x00000003".to_string(),
|
||||||
|
live_record_count: 2,
|
||||||
|
live_record_count_hex: "0x00000002".to_string(),
|
||||||
|
header_words: vec![0, 6, 0x0a, 0x14, 3, 2],
|
||||||
|
header_hex_words: vec![],
|
||||||
|
evidence: vec![],
|
||||||
|
};
|
||||||
|
let triplet_probe =
|
||||||
|
parse_save_placed_structure_record_triplet_probe(&bytes, Some(&header_probe))
|
||||||
|
.expect("placed-structure triplet probe should parse");
|
||||||
|
|
||||||
|
assert_eq!(triplet_probe.record_count, 2);
|
||||||
|
assert_eq!(triplet_probe.entries[0].primary_name, "StationA");
|
||||||
|
assert_eq!(triplet_probe.entries[0].secondary_name, "StationSetA");
|
||||||
|
assert_eq!(triplet_probe.entries[0].policy_chunk_len, 0x1a);
|
||||||
|
assert_eq!(triplet_probe.entries[0].policy_f32_lane_4, 5.9760494);
|
||||||
|
assert_eq!(triplet_probe.entries[0].policy_trailing_word, 0x0101);
|
||||||
|
assert_eq!(triplet_probe.entries[1].primary_name, "StationB");
|
||||||
|
assert_eq!(triplet_probe.entries[1].secondary_name, "StationSetB");
|
||||||
|
assert_eq!(triplet_probe.entries[1].policy_f32_lane_1, 1200.0);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_placed_structure_tagged_collection_header_probe_from_exact_u32_tags() {
|
fn parses_placed_structure_tagged_collection_header_probe_from_exact_u32_tags() {
|
||||||
let mut bytes = vec![0u8; 0x400];
|
let mut bytes = vec![0u8; 0x400];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue