unreal_asset/registry/objects/
depends_node.rs

1//! Asset bundle depends node
2
3use bitvec::{order::Lsb0, prelude::BitVec};
4use byteorder::LE;
5use lazy_static::lazy_static;
6
7use unreal_helpers::BitVecExt;
8
9use crate::custom_version::FAssetRegistryVersionType;
10use crate::error::{Error, RegistryError};
11use crate::flags::EDependencyProperty;
12use crate::reader::{archive_reader::ArchiveReader, archive_writer::ArchiveWriter};
13use crate::types::fname::FName;
14
15/// Asset identifier
16#[derive(Debug, Clone, Default)]
17pub struct AssetIdentifier {
18    /// Package name
19    pub package_name: Option<FName>,
20    /// Primary asset type
21    pub primary_asset_type: Option<FName>,
22    /// Object name
23    pub object_name: Option<FName>,
24    /// Value name
25    pub value_name: Option<FName>,
26}
27
28type LoadedDependencyNodes = (Vec<DependsNode>, Vec<DependsNode>, BitVec<u32, Lsb0>);
29
30impl AssetIdentifier {
31    /// Read an `AssetIdentifier` from an asset
32    pub fn new<Reader: ArchiveReader>(asset: &mut Reader) -> Result<Self, Error> {
33        let field_bits = asset.read_u8()?;
34        let package_name = match (field_bits & (1 << 0)) != 0 {
35            true => Some(asset.read_fname()?),
36            false => None,
37        };
38
39        let primary_asset_type = match (field_bits & (1 << 1)) != 0 {
40            true => Some(asset.read_fname()?),
41            false => None,
42        };
43
44        let object_name = match (field_bits & (1 << 2)) != 0 {
45            true => Some(asset.read_fname()?),
46            false => None,
47        };
48
49        let value_name = match (field_bits & (1 << 3)) != 0 {
50            true => Some(asset.read_fname()?),
51            false => None,
52        };
53
54        Ok(Self {
55            package_name,
56            primary_asset_type,
57            object_name,
58            value_name,
59        })
60    }
61
62    /// Write an `AssetIdentifier` to an asset
63    pub fn write<Writer: ArchiveWriter>(&self, writer: &mut Writer) -> Result<(), Error> {
64        #[allow(clippy::identity_op)]
65        let field_bits = (self.package_name.is_some() as u8) << 0u8
66            | (self.primary_asset_type.is_some() as u8) << 1u8
67            | (self.object_name.is_some() as u8) << 2u8
68            | (self.value_name.is_some() as u8) << 3u8;
69
70        writer.write_u8(field_bits)?;
71        if let Some(package_name) = &self.package_name {
72            writer.write_fname(package_name)?;
73        }
74        if let Some(primary_asset_type) = &self.primary_asset_type {
75            writer.write_fname(primary_asset_type)?;
76        }
77        if let Some(object_name) = &self.object_name {
78            writer.write_fname(object_name)?;
79        }
80        if let Some(value_name) = &self.value_name {
81            writer.write_fname(value_name)?;
82        }
83        Ok(())
84    }
85}
86
87/// Depends node
88#[derive(Clone, Debug)]
89pub struct DependsNode {
90    /// Asset identifier
91    pub identifier: AssetIdentifier,
92
93    /// Hard dependencies
94    pub hard_dependencies: Vec<DependsNode>,
95    /// Soft dependencies
96    pub soft_dependencies: Vec<DependsNode>,
97
98    /// Name dependencies
99    pub name_dependencies: Vec<DependsNode>,
100
101    /// Hard manage dependencies
102    pub hard_manage_dependencies: Vec<DependsNode>,
103    /// Soft manage dependencies
104    pub soft_manage_dependencies: Vec<DependsNode>,
105
106    /// Referencers
107    pub referencers: Vec<DependsNode>,
108
109    /// Package flags
110    pub package_flags: Option<BitVec<u32, Lsb0>>,
111    /// Manage flags
112    pub manage_flags: Option<BitVec<u32, Lsb0>>,
113
114    /// Node index
115    index: i32,
116    /// Asset registry version
117    version: FAssetRegistryVersionType,
118}
119
120#[allow(unused)]
121const PACKAGE_FLAG_WIDTH: i32 = 3;
122#[allow(unused)]
123const PACKAGE_FLAG_SET_WIDTH: i32 = 1 << PACKAGE_FLAG_WIDTH;
124#[allow(unused)]
125const MANAGE_FLAG_WIDTH: i32 = 1;
126const MANAGE_FLAG_SET_WIDTH: i32 = 1;
127
128lazy_static! {
129    static ref HARD_BIT: u8 = DependsNode::package_properties_to_byte(
130        EDependencyProperty::HARD | EDependencyProperty::GAME | EDependencyProperty::BUILD
131    );
132    static ref SOFT_BIT: u8 = DependsNode::package_properties_to_byte(
133        EDependencyProperty::GAME | EDependencyProperty::BUILD
134    );
135}
136
137#[allow(unused)]
138const HARD_MANAGE_BITS: u32 = 0x1;
139#[allow(unused)]
140const SOFT_MANAGE_BITS: u32 = 0x0;
141
142impl DependsNode {
143    /// Package `EDependencyProperty` enum into a byte
144    #[allow(clippy::identity_op)] // allow for clarity
145    fn package_properties_to_byte(properties: EDependencyProperty) -> u8 {
146        (0x1 * (properties & EDependencyProperty::HARD).bits() as u8)
147            | (0x2 * (properties & EDependencyProperty::GAME).bits() as u8)
148            | (0x4 * (properties & EDependencyProperty::BUILD).bits() as u8)
149    }
150
151    /// Read `DependsNode` dependencies
152    fn read_dependencies<Reader: ArchiveReader>(
153        asset: &mut Reader,
154        preallocated_depends_node_buffer: &Vec<DependsNode>,
155        flag_set_width: i32,
156    ) -> Result<LoadedDependencyNodes, Error> {
157        let mut sort_indexes = Vec::new();
158        let mut pointer_dependencies = Vec::new();
159
160        let in_dependencies = asset.read_array(|asset: &mut Reader| Ok(asset.read_i32::<LE>()?))?;
161
162        let num_flag_bits = flag_set_width * in_dependencies.len() as i32;
163        let num_flag_words = (num_flag_bits + 31) / 32;
164        let in_flag_bits = match num_flag_words != 0 {
165            true => BitVec::from_vec(
166                asset.read_array_with_length(num_flag_words, |asset: &mut Reader| {
167                    Ok(asset.read_u32::<LE>()?)
168                })?,
169            ),
170            false => BitVec::<u32, Lsb0>::new(),
171        };
172
173        for serialize_index in &in_dependencies {
174            if *serialize_index < 0
175                || preallocated_depends_node_buffer.len() <= *serialize_index as usize
176            {
177                return Err(RegistryError::InvalidIndex(*serialize_index).into());
178            }
179
180            let depends_node = &preallocated_depends_node_buffer[*serialize_index as usize];
181            pointer_dependencies.push(depends_node);
182        }
183
184        for i in 0..in_dependencies.len() {
185            sort_indexes.push(i as i32);
186        }
187
188        sort_indexes.sort_by(|a, b| {
189            let cmp =
190                pointer_dependencies[*a as usize].index - pointer_dependencies[*b as usize].index;
191
192            cmp.cmp(&0)
193        });
194
195        let mut hard_dependencies = Vec::new();
196        let mut soft_dependencies = Vec::new();
197
198        for index in &sort_indexes {
199            let node = pointer_dependencies[*index as usize];
200            let package_flags = node.package_flags.as_ref().ok_or_else(|| {
201                Error::invalid_file(
202                    "No package flags on asset registry with version >= AddedDependencyFlags"
203                        .to_string(),
204                )
205            })?;
206
207            if package_flags
208                .get(*HARD_BIT as usize)
209                .as_deref()
210                .copied()
211                .unwrap_or(false)
212            {
213                hard_dependencies.push(node.clone());
214            } else {
215                soft_dependencies.push(node.clone());
216            }
217        }
218
219        let mut out_flag_bits = BitVec::with_capacity(num_flag_bits as usize);
220        for write_index in 0..in_dependencies.len() as i32 {
221            let read_index = &sort_indexes[write_index as usize];
222
223            out_flag_bits.set_range_from_range(
224                write_index * flag_set_width,
225                flag_set_width,
226                &in_flag_bits,
227                read_index * flag_set_width,
228            );
229        }
230
231        Ok((hard_dependencies, soft_dependencies, out_flag_bits))
232    }
233
234    /// Write `DependsNode` dependencies
235    fn write_dependencies<Writer: ArchiveWriter>(
236        writer: &mut Writer,
237        flag_set_width: i32,
238        flags: &BitVec<u32, Lsb0>,
239        hard_dependencies: &Vec<DependsNode>,
240        soft_dependencies: &Vec<DependsNode>,
241    ) -> Result<(), Error> {
242        let dependencies_length = hard_dependencies.len() as i32 + soft_dependencies.len() as i32;
243        let mut out_flag_bits = BitVec::<u32, Lsb0>::new();
244
245        writer.write_i32::<LE>(dependencies_length)?;
246
247        for (i, hard_dependency) in hard_dependencies.iter().enumerate() {
248            writer.write_i32::<LE>(hard_dependency.index)?;
249
250            let index = out_flag_bits.len() as i32;
251            out_flag_bits.reserve(flag_set_width as usize);
252            out_flag_bits.set_range_from_range(
253                index,
254                flag_set_width,
255                flags,
256                i as i32 * flag_set_width,
257            );
258        }
259
260        let inital_soft_index = hard_dependencies.len() as i32;
261
262        for (i, soft_dependency) in soft_dependencies.iter().enumerate() {
263            writer.write_i32::<LE>(soft_dependency.index)?;
264
265            let index = out_flag_bits.len() as i32 + inital_soft_index;
266            out_flag_bits.reserve(flag_set_width as usize);
267            out_flag_bits.set_range_from_range(
268                index,
269                flag_set_width,
270                flags,
271                (i as i32 + inital_soft_index) * flag_set_width,
272            );
273        }
274
275        let bit_vec_size = ((out_flag_bits.len() + 31) / 32) as i32;
276        writer.write_i32::<LE>(bit_vec_size)?;
277
278        for byte in out_flag_bits.chunks(8).map(|chunk| {
279            let mut byte = 0u8;
280            for i in 0..8 {
281                if chunk[i] {
282                    byte |= 1 << i;
283                }
284            }
285            byte
286        }) {
287            writer.write_u8(byte)?;
288        }
289
290        Ok(())
291    }
292
293    /// Read `DependsNode` dependencies without flags
294    fn read_dependencies_no_flags<Reader: ArchiveReader>(
295        asset: &mut Reader,
296        preallocated_depends_node_buffer: &Vec<DependsNode>,
297    ) -> Result<Vec<DependsNode>, Error> {
298        let mut pointer_dependencies = Vec::new();
299        let in_dependencies = asset.read_array(|asset: &mut Reader| Ok(asset.read_i32::<LE>()?))?;
300
301        for serialize_index in &in_dependencies {
302            if *serialize_index < 0
303                || preallocated_depends_node_buffer.len() <= *serialize_index as usize
304            {
305                return Err(RegistryError::InvalidIndex(*serialize_index).into());
306            }
307
308            let depends_node = &preallocated_depends_node_buffer[*serialize_index as usize];
309            pointer_dependencies.push(depends_node);
310        }
311
312        let mut sort_indexes = Vec::new();
313
314        for i in 0..in_dependencies.len() as i32 {
315            sort_indexes.push(i);
316        }
317
318        sort_indexes.sort_by(|a, b| {
319            let cmp =
320                pointer_dependencies[*a as usize].index - pointer_dependencies[*b as usize].index;
321
322            cmp.cmp(&0)
323        });
324
325        let mut out_dependencies = Vec::with_capacity(in_dependencies.len());
326        for index in sort_indexes {
327            out_dependencies.push(pointer_dependencies[index as usize].clone());
328        }
329
330        Ok(out_dependencies)
331    }
332
333    /// Write `DependsNode` dependencies without flags
334    fn write_dependencies_no_flags<Writer: ArchiveWriter>(
335        writer: &mut Writer,
336        dependencies: &Vec<DependsNode>,
337    ) -> Result<(), Error> {
338        writer.write_i32::<LE>(dependencies.len() as i32)?;
339        for dependency in dependencies {
340            writer.write_i32::<LE>(dependency.index)?;
341        }
342        Ok(())
343    }
344
345    /// Create a new `DependsNode` instance
346    pub fn new(index: i32, version: FAssetRegistryVersionType) -> Self {
347        Self {
348            identifier: AssetIdentifier::default(),
349            hard_dependencies: Vec::new(),
350            soft_dependencies: Vec::new(),
351            name_dependencies: Vec::new(),
352            hard_manage_dependencies: Vec::new(),
353            soft_manage_dependencies: Vec::new(),
354            referencers: Vec::new(),
355            package_flags: None,
356            manage_flags: None,
357            index,
358            version,
359        }
360    }
361
362    /// Load `DependsNode` dependencies
363    pub fn load_dependencies<Reader: ArchiveReader>(
364        &mut self,
365        asset: &mut Reader,
366        preallocated_depends_node_buffer: &Vec<DependsNode>,
367    ) -> Result<(), Error> {
368        let identifier = AssetIdentifier::new(asset)?;
369
370        let (hard_dependencies, soft_dependencies, package_flags) = Self::read_dependencies(
371            asset,
372            preallocated_depends_node_buffer,
373            PACKAGE_FLAG_SET_WIDTH,
374        )?;
375
376        let name_dependencies =
377            Self::read_dependencies_no_flags(asset, preallocated_depends_node_buffer)?;
378
379        let (hard_manage_dependencies, soft_manage_dependencies, manage_flags) =
380            Self::read_dependencies(
381                asset,
382                preallocated_depends_node_buffer,
383                MANAGE_FLAG_SET_WIDTH,
384            )?;
385
386        let referencers =
387            Self::read_dependencies_no_flags(asset, preallocated_depends_node_buffer)?;
388
389        self.identifier = identifier;
390
391        self.hard_dependencies = hard_dependencies;
392        self.soft_dependencies = soft_dependencies;
393
394        self.package_flags = Some(package_flags);
395        self.name_dependencies = name_dependencies;
396
397        self.hard_manage_dependencies = hard_manage_dependencies;
398        self.soft_manage_dependencies = soft_manage_dependencies;
399
400        self.manage_flags = Some(manage_flags);
401        self.referencers = referencers;
402
403        Ok(())
404    }
405
406    /// Save `DependsNode` dependencies
407    pub fn save_dependencies<Writer: ArchiveWriter>(
408        &self,
409        writer: &mut Writer,
410    ) -> Result<(), Error> {
411        self.identifier.write(writer)?;
412
413        let package_flags = self
414            .package_flags
415            .as_ref()
416            .ok_or_else(|| RegistryError::version("Package flags".to_string(), self.version))?;
417
418        Self::write_dependencies(
419            writer,
420            PACKAGE_FLAG_SET_WIDTH,
421            package_flags,
422            &self.hard_dependencies,
423            &self.soft_dependencies,
424        )?;
425
426        Self::write_dependencies_no_flags(writer, &self.name_dependencies)?;
427
428        let manage_flags = self
429            .manage_flags
430            .as_ref()
431            .ok_or_else(|| RegistryError::version("Manage Flags".to_string(), self.version))?;
432
433        Self::write_dependencies(
434            writer,
435            MANAGE_FLAG_SET_WIDTH,
436            manage_flags,
437            &self.hard_manage_dependencies,
438            &self.soft_manage_dependencies,
439        )?;
440
441        Self::write_dependencies_no_flags(writer, &self.referencers)?;
442
443        Ok(())
444    }
445
446    /// Read `DependsNode` array
447    fn read_node_array<Reader: ArchiveReader>(
448        asset: &mut Reader,
449        preallocated_depends_node_buffer: &[DependsNode],
450        num: i32,
451        nodes: &mut Vec<DependsNode>,
452    ) -> Result<(), Error> {
453        for _ in 0..num {
454            let index = asset.read_i32::<LE>()?;
455            if index < 0 || nodes.len() <= index as usize {
456                return Err(RegistryError::InvalidIndex(index).into());
457            }
458
459            let depends_node = &preallocated_depends_node_buffer[index as usize];
460            nodes.push(depends_node.clone());
461        }
462
463        Ok(())
464    }
465
466    /// Load `DependsNode` dependencies before flags
467    pub fn load_dependencies_before_flags<Reader: ArchiveReader>(
468        &mut self,
469        asset: &mut Reader,
470        preallocated_depends_node_buffer: &[DependsNode],
471    ) -> Result<(), Error> {
472        let identifier = AssetIdentifier::new(asset)?;
473
474        let num_hard = asset.read_i32::<LE>()?;
475        let num_soft = asset.read_i32::<LE>()?;
476        let num_name = asset.read_i32::<LE>()?;
477        let num_soft_manage = asset.read_i32::<LE>()?;
478        let num_hard_manage = match self.version >= FAssetRegistryVersionType::AddedHardManage {
479            true => asset.read_i32::<LE>()?,
480            false => 0,
481        };
482        let num_referencers = asset.read_i32::<LE>()?;
483
484        let mut name_dependencies = Vec::with_capacity(num_name as usize);
485        let mut referencers = Vec::with_capacity(num_referencers as usize);
486
487        Self::read_node_array(
488            asset,
489            preallocated_depends_node_buffer,
490            num_hard,
491            &mut self.hard_dependencies,
492        )?;
493        Self::read_node_array(
494            asset,
495            preallocated_depends_node_buffer,
496            num_soft,
497            &mut self.soft_dependencies,
498        )?;
499        Self::read_node_array(
500            asset,
501            preallocated_depends_node_buffer,
502            num_name,
503            &mut name_dependencies,
504        )?;
505        Self::read_node_array(
506            asset,
507            preallocated_depends_node_buffer,
508            num_soft_manage,
509            &mut self.soft_manage_dependencies,
510        )?;
511        Self::read_node_array(
512            asset,
513            preallocated_depends_node_buffer,
514            num_hard_manage,
515            &mut self.hard_manage_dependencies,
516        )?;
517        Self::read_node_array(
518            asset,
519            preallocated_depends_node_buffer,
520            num_referencers,
521            &mut referencers,
522        )?;
523
524        self.identifier = identifier;
525        self.name_dependencies = name_dependencies;
526        self.referencers = referencers;
527
528        self.package_flags = None;
529        self.manage_flags = None;
530        Ok(())
531    }
532
533    /// Save `DependsNode` dependencies before flags
534    pub fn save_dependencies_before_flags<Writer: ArchiveWriter>(
535        &self,
536        writer: &mut Writer,
537    ) -> Result<(), Error> {
538        self.identifier.write(writer)?;
539
540        writer.write_i32::<LE>(self.hard_dependencies.len() as i32)?;
541        writer.write_i32::<LE>(self.soft_dependencies.len() as i32)?;
542        writer.write_i32::<LE>(self.name_dependencies.len() as i32)?;
543        writer.write_i32::<LE>(self.soft_manage_dependencies.len() as i32)?;
544        if self.version >= FAssetRegistryVersionType::AddedHardManage {
545            writer.write_i32::<LE>(self.hard_manage_dependencies.len() as i32)?;
546        }
547        writer.write_i32::<LE>(self.referencers.len() as i32)?;
548
549        for hard_dependency in &self.hard_dependencies {
550            writer.write_i32::<LE>(hard_dependency.index)?;
551        }
552
553        for soft_dependency in &self.soft_dependencies {
554            writer.write_i32::<LE>(soft_dependency.index)?;
555        }
556
557        for name_dependency in &self.name_dependencies {
558            writer.write_i32::<LE>(name_dependency.index)?;
559        }
560
561        for soft_manage_dependency in &self.soft_manage_dependencies {
562            writer.write_i32::<LE>(soft_manage_dependency.index)?;
563        }
564
565        if self.version >= FAssetRegistryVersionType::AddedHardManage {
566            for hard_manage_dependency in &self.hard_manage_dependencies {
567                writer.write_i32::<LE>(hard_manage_dependency.index)?;
568            }
569        }
570
571        for referencer in &self.referencers {
572            writer.write_i32::<LE>(referencer.index)?;
573        }
574
575        Ok(())
576    }
577}