Add writing support for ArrayProperty

This commit is contained in:
Joshua Goins 2025-02-23 16:50:10 -05:00
parent 80b288051c
commit 0561036f01
2 changed files with 57 additions and 20 deletions

View file

@ -1,4 +1,4 @@
use crate::common::read_string_with_length; use crate::common::{read_string_with_length, write_string_with_length};
use crate::map_property::MabSubProperty; use crate::map_property::MabSubProperty;
use binrw::{BinRead, BinResult, binrw}; use binrw::{BinRead, BinResult, binrw};
@ -24,17 +24,24 @@ pub struct ArrayEntry {
pub key: MabSubProperty, pub key: MabSubProperty,
} }
fn calc_size_in_bytes(entries: &Vec<ArrayEntry>) -> u32 {
// TODO: stub
18
}
#[binrw] #[binrw]
#[derive(Debug)] #[derive(Debug)]
pub struct ArrayProperty { pub struct ArrayProperty {
// Plus this int #[bw(calc = calc_size_in_bytes(entries))]
pub size_in_bytes: u32, pub size_in_bytes: u32,
#[br(pad_before = 4, parse_with = read_string_with_length)] #[brw(pad_before = 4)]
#[bw(ignore)] #[br(parse_with = read_string_with_length)]
#[bw(write_with = write_string_with_length)]
pub key_name: String, pub key_name: String,
#[br(pad_before = 1)] #[brw(pad_before = 1)]
#[bw(calc = 1)]
pub unk: u32, pub unk: u32,
#[br(parse_with = custom_parser, args(size_in_bytes, &key_name))] #[br(parse_with = custom_parser, args(size_in_bytes, &key_name))]
@ -45,11 +52,12 @@ pub struct ArrayProperty {
mod tests { mod tests {
use super::*; use super::*;
use crate::map_property::MabSubProperty::String; use crate::map_property::MabSubProperty::String;
use binrw::BinRead; use binrw::{BinRead, BinWrite};
use std::io::Cursor; use std::io::Cursor;
use crate::map_property::MapSubStrProperty;
#[test] #[test]
fn simple_array() { fn read_simple_array() {
// From Slot.sav // From Slot.sav
let data = [ let data = [
0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x74, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x74,
@ -59,11 +67,38 @@ mod tests {
]; ];
let mut cursor = Cursor::new(data); let mut cursor = Cursor::new(data);
let decoded = ArrayProperty::read_le(&mut cursor).unwrap(); let decoded = ArrayProperty::read_le(&mut cursor).unwrap();
assert_eq!(decoded.size_in_bytes, 18);
assert_eq!(decoded.key_name, "StrProperty"); assert_eq!(decoded.key_name, "StrProperty");
let String(value_property) = &decoded.entries.first().unwrap().key else { let String(value_property) = &decoded.entries.first().unwrap().key else {
panic!("StrProperty!") panic!("StrProperty!")
}; };
assert_eq!(value_property.value, "redstrate"); assert_eq!(value_property.value, "redstrate");
} }
#[test]
fn write_simple_array() {
let expected_data: [u8; 43] = [
0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x53, 0x74,
0x72, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x00, 0x00, 0x72, 0x65, 0x64, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65,
0x00,
];
let property = ArrayProperty {
key_name: "StrProperty".to_string(),
entries: vec![
ArrayEntry {
key: String(MapSubStrProperty {
value: "redstrate".to_string(),
}),
}
],
};
let mut buffer: Vec<u8> = Vec::new();
{
let mut cursor = Cursor::new(&mut buffer);
property.write_le(&mut cursor).unwrap();
}
assert_eq!(expected_data, &buffer[..]);
}
} }

View file

@ -1,4 +1,4 @@
use crate::common::{read_bool_from, read_string_with_length}; use crate::common::{read_bool_from, read_string_with_length, write_string_with_length};
use crate::struct_property::Struct; use crate::struct_property::Struct;
use crate::structs::PrimaryAssetNameProperty; use crate::structs::PrimaryAssetNameProperty;
use binrw::helpers::until_exclusive; use binrw::helpers::until_exclusive;
@ -26,11 +26,12 @@ pub struct MapSubStructProperty {
#[derive(Debug)] #[derive(Debug)]
pub struct StructMaybeKey { pub struct StructMaybeKey {
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub unk_name: String, pub unk_name: String,
#[br(pad_after = 8, parse_with = read_string_with_length)] #[brw(pad_after = 8)]
#[bw(ignore)] #[br(parse_with = read_string_with_length)]
#[bw(write_with = write_string_with_length)]
pub unk_type: String, pub unk_type: String,
#[br(pad_before = 4)] // type length #[br(pad_before = 4)] // type length
@ -47,7 +48,7 @@ pub struct MapSubFloatProperty {
#[derive(Debug)] #[derive(Debug)]
pub struct MapSubNameProperty { pub struct MapSubNameProperty {
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub value: String, pub value: String,
} }
@ -55,7 +56,7 @@ pub struct MapSubNameProperty {
#[derive(Debug)] #[derive(Debug)]
pub struct MapSubStrProperty { pub struct MapSubStrProperty {
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub value: String, pub value: String,
} }
@ -77,7 +78,7 @@ pub struct MapSubIntProperty {
#[derive(Debug)] #[derive(Debug)]
pub struct MapSubEnumProperty { pub struct MapSubEnumProperty {
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub value: String, pub value: String,
} }
@ -106,7 +107,7 @@ pub enum MabSubProperty {
#[derive(Debug)] #[derive(Debug)]
pub struct StringMapKey { pub struct StringMapKey {
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub value: String, pub value: String,
} }
@ -182,15 +183,16 @@ pub struct MapProperty {
// Plus this int // Plus this int
pub size_in_bytes: u32, pub size_in_bytes: u32,
#[br(pad_before = 4, parse_with = read_string_with_length)] #[brw(pad_before = 4)]
#[bw(ignore)] #[br(parse_with = read_string_with_length)]
#[bw(write_with = write_string_with_length)]
pub key_name: String, pub key_name: String,
#[br(parse_with = read_string_with_length)] #[br(parse_with = read_string_with_length)]
#[bw(ignore)] #[bw(write_with = write_string_with_length)]
pub value_name: String, pub value_name: String,
#[br(pad_before = 5)] #[brw(pad_before = 5)]
pub key_type: KeyType, pub key_type: KeyType,
#[br(parse_with = custom_parser, args(size_in_bytes, &key_type, &value_name))] #[br(parse_with = custom_parser, args(size_in_bytes, &key_type, &value_name))]