Skip to main content

microcad_core/
hash.rs

1// Copyright © 2025-2026 The µcad authors <info@microcad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Render hash functionality.
5
6use derive_more::Deref;
7
8/// Render hash type.
9pub type HashId = u64;
10
11pub use rustc_hash::FxHashMap as HashMap;
12pub use rustc_hash::FxHashSet as HashSet;
13pub use rustc_hash::FxHasher as Hasher;
14use serde::Serialize;
15
16/// Trait to implement for typed that contain a pre-computed hash value.
17pub trait ComputedHash {
18    /// Return computed hash value.
19    fn computed_hash(&self) -> HashId;
20}
21
22/// Generic wrapper that contains the hashed value.
23#[derive(Deref, Debug, Clone, Serialize)]
24#[serde(bound(serialize = "T: Serialize"))]
25pub struct Hashed<T: std::hash::Hash> {
26    #[deref]
27    inner: T,
28    hash: HashId,
29}
30
31impl<T: std::hash::Hash> Hashed<T> {
32    /// Create a new wrapper with hashed.
33    pub fn new(inner: T) -> Self {
34        let mut hasher = Hasher::default();
35        inner.hash(&mut hasher);
36        Self {
37            inner,
38            hash: std::hash::Hasher::finish(&hasher),
39        }
40    }
41
42    /// Transforms the inner value and recalculates the hash for the new value.
43    pub fn map<U: std::hash::Hash, F>(self, f: F) -> Hashed<U>
44    where
45        F: FnOnce(T) -> U,
46    {
47        // Transform the value
48        let new_inner = f(self.inner);
49
50        // Re-hash the new value to ensure the HashId stays in sync
51        Hashed::new(new_inner)
52    }
53
54    /// Return inner value.
55    pub fn value(&self) -> &T {
56        &self.inner
57    }
58}
59
60impl<T: std::hash::Hash> ComputedHash for Hashed<T> {
61    fn computed_hash(&self) -> HashId {
62        self.hash
63    }
64}