Skip to main content

frozone/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2mod types;
3
4pub use frozone_derive::Freezable;
5use heapless::Vec;
6
7pub const TYPE_RECURSION_LIMIT: usize = 1024;
8
9#[derive(Debug)]
10pub struct FreezeCtx {
11    // type, depth where type was found at
12    pub cache: Vec<(core::any::TypeId, u32), TYPE_RECURSION_LIMIT>,
13    pub depth: u32,
14}
15
16impl FreezeCtx {
17    fn new() -> Self {
18        FreezeCtx {
19            cache: Vec::new(),
20            depth: 0,
21        }
22    }
23}
24
25pub trait Freezable {
26    fn freeze() -> u64 {
27        let mut ctx = FreezeCtx::new();
28        Self::freeze_with_context(&mut ctx)
29    }
30    fn freeze_with_context(ctx: &mut FreezeCtx) -> u64;
31}
32
33/// internals to reuse from frozone-derive
34/// to simplify the code in the proc-macro
35pub mod internals {
36    pub use super::*;
37    pub use core::hash::{Hash, Hasher};
38
39    pub const TYPE_RECURSION_MESSAGE: &str = "exceeded the 1024 nested types limit";
40
41    #[cfg(not(feature = "std"))]
42    extern crate alloc;
43    #[cfg(not(feature = "std"))]
44    pub use alloc::boxed::Box;
45
46    /// "Name and Freeze"-returning function
47    pub type NF = Box<dyn Fn(&mut FreezeCtx) -> (&str, u64)>;
48    /// "(only) Freeze"-returning function
49    pub type F = Box<dyn Fn(&mut FreezeCtx) -> u64>;
50
51    pub fn nf_freeze(x: &NF, ctx: &mut FreezeCtx, acc: u64) -> u64 {
52        #[allow(deprecated)]
53        let mut hasher = core::hash::SipHasher::new();
54        let y = x(ctx);
55        y.0.hash(&mut hasher);
56        y.1.hash(&mut hasher);
57        acc.overflowing_add(hasher.finish()).0
58    }
59
60    pub fn f_freeze(x: &NF, ctx: &mut FreezeCtx, acc: u64) -> u64 {
61        #[allow(deprecated)]
62        let mut hasher = core::hash::SipHasher::new();
63        x(ctx).hash(&mut hasher);
64        acc.overflowing_add(hasher.finish()).0
65    }
66}