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 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
33pub 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 pub type NF = Box<dyn Fn(&mut FreezeCtx) -> (&str, u64)>;
48 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}