hydrate_base/
built_artifact_metadata.rs

1use crate::{ArtifactId, StringHash};
2use serde::{Deserialize, Serialize};
3use std::hash::{Hash, Hasher};
4use std::sync::Arc;
5use uuid::Uuid;
6
7/// Used to store debug manifest data. It's not needed for the game to function but can be used in
8/// addition to the release manifest to get helpful debug info
9#[derive(Serialize, Deserialize)]
10pub struct DebugArtifactManifestDataJson {
11    pub artifact_id: ArtifactId,
12    // stored as a string so we can encoded as hex
13    pub build_hash: String,
14    pub combined_build_hash: String,
15    pub symbol_name: String,
16    // stored as a string so we can encoded as hex. The hash isn't really needed but it's nice
17    // to have in the file for looking up a hash while debugging
18    pub symbol_hash: String,
19    pub artifact_type: Uuid,
20    pub debug_name: String,
21}
22
23/// Used to store debug manifest data. It's not needed for the game to function but can be used in
24/// addition to the release manifest to get helpful debug info
25#[derive(Serialize, Deserialize, Default)]
26pub struct DebugManifestFileJson {
27    pub artifacts: Vec<DebugArtifactManifestDataJson>,
28}
29
30/// Metadata about the artifact that is loaded in memory at all times. May include extra debug data.
31/// This is just enough information to know if an artifact exists and know where to get more info
32/// about it. Some data needed for load is encoded in the artifact itself and not in memory until the
33/// artifact is requested and must be fetched from disk.
34pub struct ArtifactManifestData {
35    pub artifact_id: ArtifactId,
36    pub simple_build_hash: u64,
37    pub combined_build_hash: u64,
38    // If the artifact cannot be addressed by symbol, this will be None
39    // Even if the symbol is Some, the string in the string hash might not be present. It's only
40    // a debugging aid
41    pub symbol_hash: Option<StringHash>,
42    pub artifact_type: Uuid,
43    // The debug name might not be available
44    pub debug_name: Option<Arc<String>>,
45}
46
47// No real reason this limit needs to exist, just don't want to read corrupt data and try to
48// allocate or load based on corrupt data. This is larger than a header is actually expected
49// to be.
50const MAX_HEADER_SIZE: usize = 1024 * 1024;
51
52/// Data encoded into the artifact. This is necessary for loading but is not available in memory at
53/// all times. The load process will fetch this from the top of the built artifact data.
54/// This is specifically designed to read the minimum amount of info out of the file.
55
56//TODO: Could use B3F here, but this is working fine for now.
57//TODO: Probably don't strictly need bincode either
58#[derive(Debug, Serialize, Deserialize)]
59pub struct BuiltArtifactHeaderData {
60    pub dependencies: Vec<ArtifactId>,
61    // Should be called artifact_type but this would be an unnecessary schema break
62    pub asset_type: Uuid, // size?
63}
64
65impl Hash for BuiltArtifactHeaderData {
66    fn hash<H: Hasher>(
67        &self,
68        state: &mut H,
69    ) {
70        let mut dependencies_hash = 0;
71        for dependency in &self.dependencies {
72            dependencies_hash ^= dependency.0.as_u128();
73        }
74
75        dependencies_hash.hash(state);
76        self.asset_type.hash(state);
77    }
78}
79
80impl BuiltArtifactHeaderData {
81    pub fn write_header<T: std::io::Write>(
82        &self,
83        writer: &mut T,
84    ) -> std::io::Result<()> {
85        let serialized = bincode::serialize(self).unwrap();
86        let bytes = serialized.len();
87        // Just
88        assert!(bytes <= MAX_HEADER_SIZE);
89        writer.write(&bytes.to_le_bytes())?;
90        writer.write(&serialized)?;
91
92        Ok(())
93    }
94
95    pub fn read_header<T: std::io::Read>(
96        reader: &mut T
97    ) -> std::io::Result<BuiltArtifactHeaderData> {
98        let mut length_bytes = [0u8; 8];
99        reader.read(&mut length_bytes)?;
100        let length = usize::from_le_bytes(length_bytes);
101        assert!(length <= MAX_HEADER_SIZE);
102
103        let mut read_buffer = vec![0u8; length];
104        reader.read_exact(&mut read_buffer).unwrap();
105
106        let metadata = bincode::deserialize(&read_buffer).unwrap();
107        Ok(metadata)
108    }
109}