Skip to main content

rpfm_lib/files/asset_variation_db/
v1.rs

1//---------------------------------------------------------------------------//
2// Copyright (c) 2017-2026 Ismael Gutiérrez González. All rights reserved.
3//
4// This file is part of the Rusted PackFile Manager (RPFM) project,
5// which can be found here: https://github.com/Frodo45127/rpfm.
6//
7// This file is licensed under the MIT license, which can be found here:
8// https://github.com/Frodo45127/rpfm/blob/master/LICENSE.
9//---------------------------------------------------------------------------//
10
11use crate::binary::{ReadBytes, WriteBytes};
12use crate::files::{DecodeableExtraData, Decodeable, EncodeableExtraData, Encodeable};
13use crate::utils::check_size_mismatch;
14
15use super::*;
16
17/// Version of every record of the database. No other is known.
18const RECORD_VERSION: u16 = 1;
19
20//---------------------------------------------------------------------------//
21//                    Implementation of AssetVariationDb
22//---------------------------------------------------------------------------//
23
24impl Decodeable for AssetVariationDb {
25
26    fn decode<R: ReadBytes>(data: &mut R, _extra_data: &Option<DecodeableExtraData>) -> Result<Self> {
27        let signature_bytes = data.read_slice(8, false)?;
28        if signature_bytes.as_slice() != SIGNATURE {
29            return Err(RLibError::DecodingFastBinUnsupportedSignature(signature_bytes));
30        }
31
32        let mut db = Self {
33            serialise_version: data.read_u16()?,
34            ..Default::default()
35        };
36
37        if db.serialise_version != 1 {
38            return Err(RLibError::DecodingFastBinUnsupportedVersion(String::from("AssetVariationDb"), db.serialise_version));
39        }
40
41        let category_count = data.read_u32()?;
42        db.categories = Vec::with_capacity(category_count as usize);
43        for _ in 0..category_count {
44            read_record_version(data, "VariationCategory")?;
45
46            let name = data.read_sized_string_u8()?;
47            let value_count = data.read_u32()?;
48            let values = (0..value_count).map(|_| data.read_sized_string_u8()).collect::<Result<_>>()?;
49            db.categories.push(VariationCategory { name, values });
50        }
51
52        let entry_count = data.read_u32()?;
53        db.entries = Vec::with_capacity(entry_count as usize);
54        for _ in 0..entry_count {
55            let key = data.read_sized_string_u8()?;
56            read_record_version(data, "VariationEntry")?;
57
58            let variation_count = data.read_u32()?;
59            let mut variations = Vec::with_capacity(variation_count as usize);
60            for _ in 0..variation_count {
61                read_record_version(data, "Variation")?;
62                variations.push(Variation {
63                    filename: data.read_sized_string_u8()?,
64                    flags: data.read_u32()?,
65                });
66            }
67
68            db.entries.push(VariationEntry { key, variations });
69        }
70
71        check_size_mismatch(data.stream_position()? as usize, data.len()? as usize)?;
72
73        Ok(db)
74    }
75}
76
77impl Encodeable for AssetVariationDb {
78
79    fn encode<W: WriteBytes>(&mut self, buffer: &mut W, _extra_data: &Option<EncodeableExtraData>) -> Result<()> {
80        if self.serialise_version != 1 {
81            return Err(RLibError::EncodingFastBinUnsupportedVersion(String::from("AssetVariationDb"), self.serialise_version));
82        }
83
84        buffer.write_all(SIGNATURE)?;
85        buffer.write_u16(self.serialise_version)?;
86
87        buffer.write_u32(self.categories.len() as u32)?;
88        for category in &self.categories {
89            buffer.write_u16(RECORD_VERSION)?;
90            buffer.write_sized_string_u8(&category.name)?;
91            buffer.write_u32(category.values.len() as u32)?;
92            for value in &category.values {
93                buffer.write_sized_string_u8(value)?;
94            }
95        }
96
97        buffer.write_u32(self.entries.len() as u32)?;
98        for entry in &self.entries {
99            buffer.write_sized_string_u8(&entry.key)?;
100            buffer.write_u16(RECORD_VERSION)?;
101            buffer.write_u32(entry.variations.len() as u32)?;
102            for variation in &entry.variations {
103                buffer.write_u16(RECORD_VERSION)?;
104                buffer.write_sized_string_u8(&variation.filename)?;
105                buffer.write_u32(variation.flags)?;
106            }
107        }
108
109        Ok(())
110    }
111}
112
113/// Reads the version of a record, failing if it's not the known one.
114fn read_record_version<R: ReadBytes>(data: &mut R, record: &str) -> Result<()> {
115    let version = data.read_u16()?;
116    if version != RECORD_VERSION {
117        return Err(RLibError::DecodingFastBinUnsupportedVersion(record.to_owned(), version));
118    }
119
120    Ok(())
121}