io_unity/serialized_file/
version10.rs

1use super::version13::path_id_parser;
2use super::version17::{FileIdentifier, TypeTree, TypeTreeNode};
3use super::{BuildTarget, SerializedFileCommonHeader};
4use super::{Serialized, SerializedFileFormatVersion};
5use crate::type_tree::{reader::TypeTreeObjectBinReadClassArgs, TypeField};
6use crate::until::Endian;
7use binrw::io::Cursor;
8use binrw::{binrw, NullString};
9use std::borrow::Cow;
10use std::sync::Arc;
11
12#[binrw]
13#[brw(big)]
14#[derive(Debug, PartialEq)]
15pub struct SerializedFile {
16    header: SerializedFileCommonHeader,
17    endianess: Endian,
18    reserved: [u8; 3],
19    #[br(is_little = endianess == Endian::Little)]
20    content: SerializedFileContent,
21}
22
23impl Serialized for SerializedFile {
24    fn get_serialized_file_version(&self) -> &SerializedFileFormatVersion {
25        &self.header.version
26    }
27
28    fn get_data_offset(&self) -> u64 {
29        self.header.data_offset as u64
30    }
31
32    fn get_endianess(&self) -> &Endian {
33        &self.endianess
34    }
35
36    fn get_objects_metadata(&self) -> Vec<super::Object> {
37        self.content
38            .objects
39            .iter()
40            .map(|obj| super::Object {
41                path_id: obj.path_id,
42                byte_start: obj.byte_start as u64,
43                byte_size: obj.byte_size,
44                class: obj.class_id as i32,
45                type_id: obj.type_id as usize,
46            })
47            .collect()
48    }
49
50    fn get_unity_version(&self) -> String {
51        self.content.unity_version.to_string()
52    }
53
54    fn get_target_platform(&self) -> &BuildTarget {
55        &self.content.target_platform
56    }
57
58    fn get_enable_type_tree(&self) -> bool {
59        true
60    }
61
62    fn get_type_object_args_by_type_id(
63        &self,
64        type_id: usize,
65    ) -> Option<TypeTreeObjectBinReadClassArgs> {
66        let stypetree = self
67            .content
68            .types
69            .iter()
70            .find(|tp| tp.class_id == type_id as i32)?;
71        let type_tree = &stypetree.type_tree;
72        let mut type_fields = Vec::new();
73        let mut string_reader = Cursor::new(&type_tree.string_buffer);
74
75        for tp in &type_tree.type_tree_node_blobs {
76            type_fields.push(Arc::new(Box::new(TypeTreeNode {
77                name: tp.get_name_str(&mut string_reader),
78                type_name: tp.get_type_str(&mut string_reader),
79                node: tp.clone(),
80            }) as Box<dyn TypeField + Send + Sync>))
81        }
82
83        Some(TypeTreeObjectBinReadClassArgs::new(
84            stypetree.class_id,
85            type_fields,
86        ))
87    }
88    fn get_externals(&self) -> Cow<Vec<FileIdentifier>> {
89        return Cow::Borrowed(&self.content.externals);
90    }
91}
92
93#[binrw]
94#[derive(Debug, PartialEq)]
95struct SerializedFileContent {
96    unity_version: NullString,
97    target_platform: BuildTarget,
98    type_count: u32,
99    #[br(count = type_count)]
100    types: Vec<SerializedType>,
101    big_id_enabled: i32,
102    object_count: i32,
103    #[br(args { count: object_count as usize, inner: ObjectBinReadArgs::builder().big_id_enabled(big_id_enabled != 0).finalize() })]
104    objects: Vec<Object>,
105    externals_count: i32,
106    #[br(count = externals_count)]
107    externals: Vec<FileIdentifier>,
108    user_information: NullString,
109}
110
111#[binrw]
112#[derive(Debug, PartialEq)]
113pub struct SerializedType {
114    pub class_id: i32,
115    pub type_tree: TypeTree,
116}
117
118#[binrw]
119#[br(import { big_id_enabled: bool})]
120#[derive(Debug, PartialEq)]
121pub struct Object {
122    #[br(parse_with = path_id_parser, args (big_id_enabled))]
123    pub path_id: i64,
124    pub byte_start: u32,
125    pub byte_size: u32,
126    pub type_id: i32,
127    pub class_id: u16,
128    pub is_destroyed: u16,
129}