1use crate::{key::StableKey, slot::MemoryManagerSlot};
2use serde::Serialize;
3
4#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
16#[cfg_attr(any(test, feature = "test-support"), derive(serde::Deserialize))]
17#[serde(deny_unknown_fields)]
18pub struct AllocationDeclaration {
19 pub(crate) stable_key: StableKey,
21 pub(crate) slot: MemoryManagerSlot,
23}
24
25impl AllocationDeclaration {
26 #[must_use]
28 pub const fn stable_key(&self) -> &StableKey {
29 &self.stable_key
30 }
31
32 #[must_use]
34 pub const fn slot(&self) -> &MemoryManagerSlot {
35 &self.slot
36 }
37}
38
39pub fn declaration_for_key<'a>(
42 declarations: &'a [AllocationDeclaration],
43 key: &str,
44) -> Option<&'a AllocationDeclaration> {
45 declarations
46 .iter()
47 .find(|declaration| declaration.stable_key.as_str() == key)
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use crate::{slot::MemoryManagerSlot, testing::DeclarationSnapshotError};
54
55 fn declaration(key: &str, id: u8) -> AllocationDeclaration {
56 AllocationDeclaration::new(key, MemoryManagerSlot::new(id).expect("usable slot"))
57 .expect("declaration")
58 }
59
60 #[test]
61 fn memory_manager_declaration_constructor_builds_common_declaration() {
62 let declaration =
63 AllocationDeclaration::memory_manager("app.orders.v1", 100).expect("declaration");
64
65 assert_eq!(declaration.stable_key.as_str(), "app.orders.v1");
66 assert_eq!(
67 declaration.slot,
68 MemoryManagerSlot::new(100).expect("usable slot")
69 );
70 }
71
72 #[test]
73 fn memory_manager_declaration_constructor_rejects_invalid_slot() {
74 let err = AllocationDeclaration::memory_manager("app.orders.v1", u8::MAX)
75 .expect_err("sentinel must fail");
76
77 assert!(matches!(
78 err,
79 DeclarationSnapshotError::MemoryManagerSlot(_)
80 ));
81 }
82
83 #[test]
84 fn declaration_decode_rejects_unusable_memory_manager_slot() {
85 let mut value = serde_json::to_value(declaration("app.orders.v1", 100)).unwrap();
86 value["slot"] = serde_json::json!(255);
87 assert!(serde_json::from_value::<AllocationDeclaration>(value.clone()).is_err());
88 let bytes = crate::test_cbor::to_vec(&value).unwrap();
89 assert!(crate::test_cbor::from_slice::<AllocationDeclaration>(&bytes).is_err());
90 }
91}