1use alloc::{boxed::Box, string::String, vec::Vec};
9use core::{fmt, ops::Deref};
10
11use buggy::{Bug, BugExt};
12use serde::{Deserialize, Serialize};
13
14use crate::{Address, Command, CommandId, PolicyId, Prior};
15
16pub mod linear;
17pub mod memory;
18
19pub const MAX_COMMAND_LENGTH: usize = 2048;
21
22aranya_crypto::custom_id! {
23 pub struct GraphId;
25}
26
27#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
28pub struct Location {
29 pub segment: usize,
30 pub command: usize,
31}
32
33impl From<(usize, usize)> for Location {
34 fn from((segment, command): (usize, usize)) -> Self {
35 Self::new(segment, command)
36 }
37}
38
39impl AsRef<Location> for Location {
40 fn as_ref(&self) -> &Location {
41 self
42 }
43}
44
45impl Location {
46 pub fn new(segment: usize, command: usize) -> Location {
47 Location { segment, command }
48 }
49
50 #[must_use]
53 pub fn previous(mut self) -> Option<Self> {
54 if let Some(n) = usize::checked_sub(self.command, 1) {
55 self.command = n;
56 Some(self)
57 } else {
58 None
59 }
60 }
61
62 pub fn same_segment(self, other: Location) -> bool {
64 self.segment == other.segment
65 }
66}
67
68impl fmt::Display for Location {
69 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70 write!(f, "{}:{}", self.segment, self.command)
71 }
72}
73
74#[derive(Debug, PartialEq, Eq, thiserror::Error)]
76pub enum StorageError {
77 #[error("storage already exists")]
78 StorageExists,
79 #[error("no such storage")]
80 NoSuchStorage,
81 #[error("segment index {} is out of bounds", .0.segment)]
82 SegmentOutOfBounds(Location),
83 #[error("command index {} is out of bounds in segment {}", .0.command, .0.segment)]
84 CommandOutOfBounds(Location),
85 #[error("IO error")]
86 IoError,
87 #[error("not a merge command")]
88 NotMerge,
89 #[error("command with id {0} not found")]
90 NoSuchId(CommandId),
91 #[error("policy mismatch")]
92 PolicyMismatch,
93 #[error("cannot write an empty perspective")]
94 EmptyPerspective,
95 #[error("segment must be a descendant of the head for commit")]
96 HeadNotAncestor,
97 #[error("command's parents do not match the perspective head")]
98 PerspectiveHeadMismatch,
99 #[error(transparent)]
100 Bug(#[from] Bug),
101}
102
103pub trait StorageProvider {
105 type Perspective: Perspective + Revertable;
106 type Segment: Segment;
107 type Storage: Storage<
108 Segment = Self::Segment,
109 Perspective = Self::Perspective,
110 FactIndex = <Self::Segment as Segment>::FactIndex,
111 >;
112
113 fn new_perspective(&mut self, policy_id: PolicyId) -> Self::Perspective;
119
120 fn new_storage(
127 &mut self,
128 init: Self::Perspective,
129 ) -> Result<(GraphId, &mut Self::Storage), StorageError>;
130
131 fn get_storage(&mut self, graph: GraphId) -> Result<&mut Self::Storage, StorageError>;
137}
138
139pub trait Storage {
142 type Perspective: Perspective + Revertable;
143 type FactPerspective: FactPerspective;
144 type Segment: Segment<FactIndex = Self::FactIndex>;
145 type FactIndex: FactIndex;
146
147 fn get_location(&self, address: Address) -> Result<Option<Location>, StorageError> {
150 self.get_location_from(self.get_head()?, address)
151 }
152
153 fn get_location_from(
155 &self,
156 start: Location,
157 address: Address,
158 ) -> Result<Option<Location>, StorageError> {
159 let mut queue = Vec::new();
160 queue.push(start);
161 'outer: while let Some(loc) = queue.pop() {
162 let head = self.get_segment(loc)?;
163 if address.max_cut > head.longest_max_cut()? {
164 continue;
165 }
166 if let Some(loc) = head.get_from_max_cut(address.max_cut)? {
167 let command = head.get_command(loc).assume("command must exist")?;
168 if command.id() == address.id {
169 return Ok(Some(loc));
170 }
171 }
172 for (skip, max_cut) in head.skip_list() {
175 if max_cut >= &address.max_cut {
176 queue.push(*skip);
177 continue 'outer;
178 }
179 }
180 queue.extend(head.prior());
181 }
182 Ok(None)
183 }
184
185 fn get_command_id(&self, location: Location) -> Result<CommandId, StorageError>;
187
188 fn get_linear_perspective(
190 &self,
191 parent: Location,
192 ) -> Result<Option<Self::Perspective>, StorageError>;
193
194 fn get_fact_perspective(&self, first: Location) -> Result<Self::FactPerspective, StorageError>;
197
198 fn new_merge_perspective(
200 &self,
201 left: Location,
202 right: Location,
203 last_common_ancestor: (Location, usize),
204 policy_id: PolicyId,
205 braid: Self::FactIndex,
206 ) -> Result<Option<Self::Perspective>, StorageError>;
207
208 fn get_segment(&self, location: Location) -> Result<Self::Segment, StorageError>;
210
211 fn get_head(&self) -> Result<Location, StorageError>;
213
214 fn commit(&mut self, segment: Self::Segment) -> Result<(), StorageError>;
217
218 fn write(&mut self, perspective: Self::Perspective) -> Result<Self::Segment, StorageError>;
220
221 fn write_facts(
223 &mut self,
224 fact_perspective: Self::FactPerspective,
225 ) -> Result<Self::FactIndex, StorageError>;
226
227 fn is_ancestor(
229 &self,
230 search_location: Location,
231 segment: &Self::Segment,
232 ) -> Result<bool, StorageError> {
233 let mut queue = Vec::new();
234 queue.extend(segment.prior());
235 let segment = self.get_segment(search_location)?;
236 let address = segment
237 .get_command(search_location)
238 .assume("location must exist")?
239 .address()?;
240 'outer: while let Some(location) = queue.pop() {
241 if location.segment == search_location.segment
242 && location.command >= search_location.command
243 {
244 return Ok(true);
245 }
246 let segment = self.get_segment(location)?;
247 if address.max_cut > segment.longest_max_cut()? {
248 continue;
249 }
250 for (skip, max_cut) in segment.skip_list() {
251 if max_cut >= &address.max_cut {
252 queue.push(*skip);
253 continue 'outer;
254 }
255 }
256 queue.extend(segment.prior());
257 }
258 Ok(false)
259 }
260}
261
262type MaxCut = usize;
263
264pub trait Segment {
274 type FactIndex: FactIndex;
275 type Command<'a>: Command
276 where
277 Self: 'a;
278
279 fn head(&self) -> Result<Self::Command<'_>, StorageError>;
281
282 fn first(&self) -> Self::Command<'_>;
284
285 fn head_location(&self) -> Location;
287
288 fn first_location(&self) -> Location;
290
291 fn contains(&self, location: Location) -> bool;
293
294 fn policy(&self) -> PolicyId;
296
297 fn prior(&self) -> Prior<Location>;
299
300 fn get_command(&self, location: Location) -> Option<Self::Command<'_>>;
302
303 fn get_from_max_cut(&self, max_cut: usize) -> Result<Option<Location>, StorageError>;
305
306 fn get_from(&self, location: Location) -> Vec<Self::Command<'_>>;
308
309 fn facts(&self) -> Result<Self::FactIndex, StorageError>;
311
312 fn contains_any<I>(&self, locations: I) -> bool
313 where
314 I: IntoIterator,
315 I::Item: AsRef<Location>,
316 {
317 locations
318 .into_iter()
319 .any(|loc| self.contains(*loc.as_ref()))
320 }
321
322 fn shortest_max_cut(&self) -> MaxCut;
326
327 fn longest_max_cut(&self) -> Result<MaxCut, StorageError>;
331
332 fn skip_list(&self) -> &[(Location, MaxCut)];
341}
342
343pub trait FactIndex: Query {}
345
346pub trait Perspective: FactPerspective {
349 fn policy(&self) -> PolicyId;
351
352 fn add_command(&mut self, command: &impl Command) -> Result<usize, StorageError>;
355
356 fn includes(&self, id: CommandId) -> bool;
358
359 fn head_address(&self) -> Result<Prior<Address>, Bug>;
361}
362
363pub trait FactPerspective: QueryMut {}
365
366pub trait Revertable {
369 fn checkpoint(&self) -> Checkpoint;
371
372 fn revert(&mut self, checkpoint: Checkpoint) -> Result<(), Bug>;
374}
375
376pub struct Checkpoint {
378 pub index: usize,
380}
381
382pub trait Query {
389 fn query(&self, name: &str, keys: &[Box<[u8]>]) -> Result<Option<Box<[u8]>>, StorageError>;
391
392 type QueryIterator: Iterator<Item = Result<Fact, StorageError>>;
394
395 fn query_prefix(
400 &self,
401 name: &str,
402 prefix: &[Box<[u8]>],
403 ) -> Result<Self::QueryIterator, StorageError>;
404}
405
406#[derive(Debug, PartialEq, Eq)]
408pub struct Fact {
409 pub key: Keys,
411 pub value: Box<[u8]>,
413}
414
415pub trait QueryMut: Query {
419 fn insert(&mut self, name: String, keys: Keys, value: Box<[u8]>);
423
424 fn delete(&mut self, name: String, keys: Keys);
426}
427
428#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
430pub struct Keys(Box<[Box<[u8]>]>);
431
432impl Deref for Keys {
433 type Target = [Box<[u8]>];
434 fn deref(&self) -> &[Box<[u8]>] {
435 self.0.as_ref()
436 }
437}
438
439impl AsRef<[Box<[u8]>]> for Keys {
440 fn as_ref(&self) -> &[Box<[u8]>] {
441 self.0.as_ref()
442 }
443}
444
445impl core::borrow::Borrow<[Box<[u8]>]> for Keys {
446 fn borrow(&self) -> &[Box<[u8]>] {
447 self.0.as_ref()
448 }
449}
450
451impl From<&[&[u8]]> for Keys {
452 fn from(value: &[&[u8]]) -> Self {
453 value.iter().copied().collect()
454 }
455}
456
457impl Keys {
458 fn starts_with(&self, prefix: &[Box<[u8]>]) -> bool {
459 self.as_ref().starts_with(prefix)
460 }
461}
462
463impl<B: Into<Box<[u8]>>> FromIterator<B> for Keys {
464 fn from_iter<T: IntoIterator<Item = B>>(iter: T) -> Self {
465 Self(iter.into_iter().map(Into::into).collect())
466 }
467}
468
469