1use alloc::{boxed::Box, string::String, vec::Vec};
9use core::{fmt, ops::Deref};
10
11use buggy::{Bug, BugExt as _};
12use serde::{Deserialize, Serialize};
13
14use crate::{Address, CmdId, Command, PolicyId, Prior};
15
16pub mod linear;
17pub mod memory;
18
19#[cfg(feature = "low-mem-usage")]
20pub const MAX_COMMAND_LENGTH: usize = 400;
21#[cfg(not(feature = "low-mem-usage"))]
22pub const MAX_COMMAND_LENGTH: usize = 2048;
23
24aranya_crypto::custom_id! {
25 pub struct GraphId;
27}
28
29#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
30pub struct Location {
31 pub segment: usize,
32 pub command: usize,
33}
34
35impl From<(usize, usize)> for Location {
36 fn from((segment, command): (usize, usize)) -> Self {
37 Self::new(segment, command)
38 }
39}
40
41impl AsRef<Self> for Location {
42 fn as_ref(&self) -> &Self {
43 self
44 }
45}
46
47impl Location {
48 pub fn new(segment: usize, command: usize) -> Self {
49 Self { segment, command }
50 }
51
52 #[must_use]
55 pub fn previous(mut self) -> Option<Self> {
56 if let Some(n) = usize::checked_sub(self.command, 1) {
57 self.command = n;
58 Some(self)
59 } else {
60 None
61 }
62 }
63
64 pub fn same_segment(self, other: Self) -> bool {
66 self.segment == other.segment
67 }
68}
69
70impl fmt::Display for Location {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "{}:{}", self.segment, self.command)
73 }
74}
75
76#[derive(Debug, PartialEq, Eq, thiserror::Error)]
78pub enum StorageError {
79 #[error("storage already exists")]
80 StorageExists,
81 #[error("no such storage")]
82 NoSuchStorage,
83 #[error("segment index {} is out of bounds", .0.segment)]
84 SegmentOutOfBounds(Location),
85 #[error("command index {} is out of bounds in segment {}", .0.command, .0.segment)]
86 CommandOutOfBounds(Location),
87 #[error("IO error")]
88 IoError,
89 #[error("not a merge command")]
90 NotMerge,
91 #[error("command with id {0} not found")]
92 NoSuchId(CmdId),
93 #[error("policy mismatch")]
94 PolicyMismatch,
95 #[error("cannot write an empty perspective")]
96 EmptyPerspective,
97 #[error("segment must be a descendant of the head for commit")]
98 HeadNotAncestor,
99 #[error("command's parents do not match the perspective head")]
100 PerspectiveHeadMismatch,
101 #[error(transparent)]
102 Bug(#[from] Bug),
103}
104
105pub trait StorageProvider {
107 type Perspective: Perspective + Revertable;
108 type Segment: Segment;
109 type Storage: Storage<
110 Segment = Self::Segment,
111 Perspective = Self::Perspective,
112 FactIndex = <Self::Segment as Segment>::FactIndex,
113 >;
114
115 fn new_perspective(&mut self, policy_id: PolicyId) -> Self::Perspective;
121
122 fn new_storage(
129 &mut self,
130 init: Self::Perspective,
131 ) -> Result<(GraphId, &mut Self::Storage), StorageError>;
132
133 fn get_storage(&mut self, graph: GraphId) -> Result<&mut Self::Storage, StorageError>;
139
140 fn remove_storage(&mut self, graph: GraphId) -> Result<(), StorageError>;
146
147 fn list_graph_ids(
150 &mut self,
151 ) -> Result<impl Iterator<Item = Result<GraphId, StorageError>>, StorageError>;
152}
153
154pub trait Storage {
157 type Perspective: Perspective + Revertable;
158 type FactPerspective: FactPerspective;
159 type Segment: Segment<FactIndex = Self::FactIndex>;
160 type FactIndex: FactIndex;
161
162 fn get_location(&self, address: Address) -> Result<Option<Location>, StorageError> {
165 self.get_location_from(self.get_head()?, address)
166 }
167
168 fn get_location_from(
170 &self,
171 start: Location,
172 address: Address,
173 ) -> Result<Option<Location>, StorageError> {
174 let mut queue = Vec::new();
175 queue.push(start);
176 'outer: while let Some(loc) = queue.pop() {
177 let head = self.get_segment(loc)?;
178 if address.max_cut > head.longest_max_cut()? {
179 continue;
180 }
181 if let Some(loc) = head.get_by_address(address) {
182 return Ok(Some(loc));
183 }
184 for (skip, max_cut) in head.skip_list() {
187 if max_cut >= &address.max_cut {
188 queue.push(*skip);
189 continue 'outer;
190 }
191 }
192 queue.extend(head.prior());
193 }
194 Ok(None)
195 }
196
197 fn get_command_address(&self, location: Location) -> Result<Address, StorageError> {
201 let segment = self.get_segment(location)?;
202 let command = segment
203 .get_command(location)
204 .ok_or(StorageError::CommandOutOfBounds(location))?;
205 let address = command.address()?;
206 Ok(address)
207 }
208
209 fn get_linear_perspective(&self, parent: Location) -> Result<Self::Perspective, StorageError>;
211
212 fn get_fact_perspective(&self, first: Location) -> Result<Self::FactPerspective, StorageError>;
215
216 fn new_merge_perspective(
218 &self,
219 left: Location,
220 right: Location,
221 last_common_ancestor: (Location, usize),
222 policy_id: PolicyId,
223 braid: Self::FactIndex,
224 ) -> Result<Self::Perspective, StorageError>;
225
226 fn get_segment(&self, location: Location) -> Result<Self::Segment, StorageError>;
228
229 fn get_head(&self) -> Result<Location, StorageError>;
231
232 fn get_head_address(&self) -> Result<Address, StorageError> {
234 self.get_command_address(self.get_head()?)
235 }
236
237 fn commit(&mut self, segment: Self::Segment) -> Result<(), StorageError>;
240
241 fn write(&mut self, perspective: Self::Perspective) -> Result<Self::Segment, StorageError>;
243
244 fn write_facts(
246 &mut self,
247 fact_perspective: Self::FactPerspective,
248 ) -> Result<Self::FactIndex, StorageError>;
249
250 fn is_ancestor(
252 &self,
253 search_location: Location,
254 segment: &Self::Segment,
255 ) -> Result<bool, StorageError> {
256 let mut queue = Vec::new();
257 queue.extend(segment.prior());
258 let segment = self.get_segment(search_location)?;
259 let address = segment
260 .get_command(search_location)
261 .assume("location must exist")?
262 .address()?;
263 'outer: while let Some(location) = queue.pop() {
264 if location.segment == search_location.segment
265 && location.command >= search_location.command
266 {
267 return Ok(true);
268 }
269 let segment = self.get_segment(location)?;
270 if address.max_cut > segment.longest_max_cut()? {
271 continue;
272 }
273 for (skip, max_cut) in segment.skip_list() {
274 if max_cut >= &address.max_cut {
275 queue.push(*skip);
276 continue 'outer;
277 }
278 }
279 queue.extend(segment.prior());
280 }
281 Ok(false)
282 }
283}
284
285type MaxCut = usize;
286
287pub trait Segment {
297 type FactIndex: FactIndex;
298 type Command<'a>: Command
299 where
300 Self: 'a;
301
302 fn head(&self) -> Result<Self::Command<'_>, StorageError>;
304
305 fn first(&self) -> Self::Command<'_>;
307
308 fn head_location(&self) -> Location;
310
311 fn first_location(&self) -> Location;
313
314 fn contains(&self, location: Location) -> bool;
316
317 fn policy(&self) -> PolicyId;
319
320 fn prior(&self) -> Prior<Location>;
322
323 fn get_command(&self, location: Location) -> Option<Self::Command<'_>>;
325
326 fn get_by_address(&self, address: Address) -> Option<Location>;
328
329 fn get_from(&self, location: Location) -> Vec<Self::Command<'_>>;
331
332 fn facts(&self) -> Result<Self::FactIndex, StorageError>;
334
335 fn contains_any<I>(&self, locations: I) -> bool
336 where
337 I: IntoIterator,
338 I::Item: AsRef<Location>,
339 {
340 locations
341 .into_iter()
342 .any(|loc| self.contains(*loc.as_ref()))
343 }
344
345 fn shortest_max_cut(&self) -> MaxCut;
349
350 fn longest_max_cut(&self) -> Result<MaxCut, StorageError>;
354
355 fn skip_list(&self) -> &[(Location, MaxCut)];
364}
365
366pub trait FactIndex: Query {}
368
369pub trait Perspective: FactPerspective {
372 fn policy(&self) -> PolicyId;
374
375 fn add_command(&mut self, command: &impl Command) -> Result<usize, StorageError>;
378
379 fn includes(&self, id: CmdId) -> bool;
381
382 fn head_address(&self) -> Result<Prior<Address>, Bug>;
384}
385
386pub trait FactPerspective: QueryMut {}
388
389pub trait Revertable {
392 fn checkpoint(&self) -> Checkpoint;
394
395 fn revert(&mut self, checkpoint: Checkpoint) -> Result<(), Bug>;
397}
398
399pub struct Checkpoint {
401 pub index: usize,
403}
404
405pub trait Query {
412 fn query(&self, name: &str, keys: &[Box<[u8]>]) -> Result<Option<Box<[u8]>>, StorageError>;
414
415 type QueryIterator: Iterator<Item = Result<Fact, StorageError>>;
417
418 fn query_prefix(
423 &self,
424 name: &str,
425 prefix: &[Box<[u8]>],
426 ) -> Result<Self::QueryIterator, StorageError>;
427}
428
429#[derive(Debug, PartialEq, Eq)]
431pub struct Fact {
432 pub key: Keys,
434 pub value: Box<[u8]>,
436}
437
438pub trait QueryMut: Query {
442 fn insert(&mut self, name: String, keys: Keys, value: Box<[u8]>);
446
447 fn delete(&mut self, name: String, keys: Keys);
449}
450
451#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
453pub struct Keys(Box<[Box<[u8]>]>);
454
455impl Deref for Keys {
456 type Target = [Box<[u8]>];
457 fn deref(&self) -> &[Box<[u8]>] {
458 self.0.as_ref()
459 }
460}
461
462impl AsRef<[Box<[u8]>]> for Keys {
463 fn as_ref(&self) -> &[Box<[u8]>] {
464 self.0.as_ref()
465 }
466}
467
468impl core::borrow::Borrow<[Box<[u8]>]> for Keys {
469 fn borrow(&self) -> &[Box<[u8]>] {
470 self.0.as_ref()
471 }
472}
473
474impl From<&[&[u8]]> for Keys {
475 fn from(value: &[&[u8]]) -> Self {
476 value.iter().copied().collect()
477 }
478}
479
480impl Keys {
481 fn starts_with(&self, prefix: &[Box<[u8]>]) -> bool {
482 self.as_ref().starts_with(prefix)
483 }
484}
485
486impl<B: Into<Box<[u8]>>> FromIterator<B> for Keys {
487 fn from_iter<T: IntoIterator<Item = B>>(iter: T) -> Self {
488 Self(iter.into_iter().map(Into::into).collect())
489 }
490}
491
492