bones_asset/
cid.rs

1use serde::{Deserialize, Serialize};
2
3#[cfg(feature = "cid_debug_trace")]
4pub(crate) use cid_debug_trace::*;
5
6/// A unique content ID.
7///
8/// Represents the Sha-256 hash of the contents of a [`LoadedAsset`][crate::LoadedAsset].
9#[derive(Clone, Copy, Eq, PartialEq, Hash, Default, PartialOrd, Ord, Serialize, Deserialize)]
10#[repr(transparent)]
11pub struct Cid(pub [u8; 32]);
12
13impl std::fmt::Display for Cid {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        write!(f, "{}", bs58::encode(self.0).into_string())
16    }
17}
18
19impl std::fmt::Debug for Cid {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        write!(f, "Cid({})", self)
22    }
23}
24
25impl Cid {
26    /// Update the CID by combining it's current data with the hash of the provided bytes.
27    pub fn update(&mut self, bytes: &[u8]) {
28        use sha2::Digest;
29        let pre_hash = self.0;
30        let mut hasher = sha2::Sha256::new();
31        hasher.update(pre_hash);
32        hasher.update(bytes);
33        let result = hasher.finalize();
34        self.0.copy_from_slice(&result);
35    }
36}
37
38#[cfg(feature = "cid_debug_trace")]
39mod cid_debug_trace {
40
41    use crate::{AssetLoc, Cid};
42    use std::path::Path;
43
44    use bones_utils::default;
45    use ustr::Ustr;
46
47    pub(crate) struct CidDebugTrace<'a> {
48        pub schema_full_name: Ustr,
49        pub file_path: &'a Path,
50
51        pub cid_after_schema_fullname: Cid,
52        pub cid_after_contents: Cid,
53
54        /// Tuple of dep_cid, updated cid, and dep asset loc
55        pub cid_after_deps: Vec<(Cid, Cid, Option<AssetLoc>)>,
56
57        pub final_cid: Cid,
58    }
59
60    impl<'a> CidDebugTrace<'a> {
61        pub(crate) fn new(schema_full_name: Ustr, file_path: &'a Path) -> Self {
62            Self {
63                schema_full_name,
64                file_path,
65                cid_after_schema_fullname: default(),
66                cid_after_contents: default(),
67                cid_after_deps: default(),
68                final_cid: default(),
69            }
70        }
71    }
72
73    impl<'a> std::fmt::Display for CidDebugTrace<'a> {
74        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75            // dump asset meta
76            writeln!(
77                f,
78                "Cid trace schema: {:?} file path: {:?}",
79                self.schema_full_name, self.file_path
80            )?;
81            writeln!(f, "Trace is in order of updates, which impacts result")?;
82
83            // cid schema fullname update
84            writeln!(
85                f,
86                "[Intermediate] Cid from schema fullname: {:?} cid: {}",
87                self.schema_full_name, self.cid_after_schema_fullname
88            )?;
89
90            // cid content update
91            writeln!(
92                f,
93                "[Intermediate] Cid from contents: cid: {}",
94                self.cid_after_contents
95            )?;
96
97            // cid dependency update
98            writeln!(f, "Dumping updates from sorted dependency cids:")?;
99            for (dep_cid, updated_cid, dep_asset_loc) in self.cid_after_deps.iter() {
100                writeln!(
101                    f,
102                    "    dep_cid: {}, cid: {}, dep_asset_loc: {:?}",
103                    dep_cid, updated_cid, dep_asset_loc
104                )?;
105            }
106
107            // final cid
108            writeln!(f, "Final cid: {}", self.final_cid)?;
109
110            Ok(())
111        }
112    }
113}