1use crate::{
2 declaration::AllocationDeclaration, key::StableKey, slot::AllocationSlotDescriptor,
3 substrate::StorageSubstrate,
4};
5use std::sync::Arc;
6
7#[derive(Clone, Debug, Eq, PartialEq)]
23pub struct ValidatedAllocations {
24 inner: Arc<ValidatedState>,
25 _private: (),
26}
27
28#[derive(Clone, Debug, Eq, PartialEq)]
29struct ValidatedState {
30 base_generation: u64,
32 declarations: Vec<AllocationDeclaration>,
34 runtime_fingerprint: Option<String>,
36}
37
38impl ValidatedAllocations {
39 pub(crate) fn new(
40 base_generation: u64,
41 declarations: Vec<AllocationDeclaration>,
42 runtime_fingerprint: Option<String>,
43 ) -> Self {
44 Self {
45 inner: Arc::new(ValidatedState {
46 base_generation,
47 declarations,
48 runtime_fingerprint,
49 }),
50 _private: (),
51 }
52 }
53
54 #[must_use]
56 pub fn base_generation(&self) -> u64 {
57 self.inner.base_generation
58 }
59
60 #[must_use]
62 pub fn declarations(&self) -> &[AllocationDeclaration] {
63 &self.inner.declarations
64 }
65
66 #[must_use]
68 pub fn runtime_fingerprint(&self) -> Option<&str> {
69 self.inner.runtime_fingerprint.as_deref()
70 }
71
72 #[must_use]
74 pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
75 self.declarations()
76 .iter()
77 .find(|declaration| &declaration.stable_key == key)
78 .map(|declaration| &declaration.slot)
79 }
80
81 pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
82 CommittedAllocations {
83 validated: self,
84 generation,
85 _private: (),
86 }
87 }
88}
89
90#[derive(Clone, Debug, Eq, PartialEq)]
103pub struct CommittedAllocations {
104 validated: ValidatedAllocations,
105 generation: u64,
106 _private: (),
107}
108
109impl CommittedAllocations {
110 #[must_use]
112 pub const fn generation(&self) -> u64 {
113 self.generation
114 }
115
116 #[must_use]
118 pub fn declarations(&self) -> &[AllocationDeclaration] {
119 self.validated.declarations()
120 }
121
122 #[must_use]
124 pub fn runtime_fingerprint(&self) -> Option<&str> {
125 self.validated.runtime_fingerprint()
126 }
127
128 #[must_use]
130 pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
131 self.validated.slot_for(key)
132 }
133
134 pub(crate) fn without_stable_key_prefix(mut self, prefix: &str) -> Self {
135 let mut state = (*self.validated.inner).clone();
136 state
137 .declarations
138 .retain(|declaration| !declaration.stable_key.as_str().starts_with(prefix));
139 self.validated.inner = Arc::new(state);
140 self
141 }
142}
143
144pub struct AllocationSession<S: StorageSubstrate> {
154 substrate: S,
155 committed: CommittedAllocations,
156}
157
158impl<S: StorageSubstrate> AllocationSession<S> {
159 #[must_use]
161 pub const fn new(substrate: S, committed: CommittedAllocations) -> Self {
162 Self {
163 substrate,
164 committed,
165 }
166 }
167
168 #[must_use]
170 pub const fn committed(&self) -> &CommittedAllocations {
171 &self.committed
172 }
173
174 pub fn open(
176 &self,
177 key: &StableKey,
178 ) -> Result<S::MemoryHandle, AllocationSessionError<S::Error>> {
179 let slot = self
180 .committed
181 .slot_for(key)
182 .ok_or_else(|| AllocationSessionError::UnknownStableKey(key.clone()))?;
183 self.substrate
184 .open_slot(slot)
185 .map_err(AllocationSessionError::Substrate)
186 }
187}
188
189#[non_exhaustive]
194#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
195pub enum AllocationSessionError<E> {
196 #[error("stable key '{0}' was not committed for this allocation session")]
198 UnknownStableKey(StableKey),
199 #[error("storage substrate failed to open allocation slot")]
201 Substrate(E),
202}