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 fn list_graph_ids(
141 &mut self,
142 ) -> Result<impl Iterator<Item = Result<GraphId, StorageError>>, StorageError>;
143}
144
145pub trait Storage {
148 type Perspective: Perspective + Revertable;
149 type FactPerspective: FactPerspective;
150 type Segment: Segment<FactIndex = Self::FactIndex>;
151 type FactIndex: FactIndex;
152
153 fn get_location(&self, address: Address) -> Result<Option<Location>, StorageError> {
156 self.get_location_from(self.get_head()?, address)
157 }
158
159 fn get_location_from(
161 &self,
162 start: Location,
163 address: Address,
164 ) -> Result<Option<Location>, StorageError> {
165 let mut queue = Vec::new();
166 queue.push(start);
167 'outer: while let Some(loc) = queue.pop() {
168 let head = self.get_segment(loc)?;
169 if address.max_cut > head.longest_max_cut()? {
170 continue;
171 }
172 if let Some(loc) = head.get_from_max_cut(address.max_cut)? {
173 let command = head.get_command(loc).assume("command must exist")?;
174 if command.id() == address.id {
175 return Ok(Some(loc));
176 }
177 }
178 for (skip, max_cut) in head.skip_list() {
181 if max_cut >= &address.max_cut {
182 queue.push(*skip);
183 continue 'outer;
184 }
185 }
186 queue.extend(head.prior());
187 }
188 Ok(None)
189 }
190
191 fn get_command_id(&self, location: Location) -> Result<CommandId, StorageError>;
193
194 fn get_linear_perspective(
196 &self,
197 parent: Location,
198 ) -> Result<Option<Self::Perspective>, StorageError>;
199
200 fn get_fact_perspective(&self, first: Location) -> Result<Self::FactPerspective, StorageError>;
203
204 fn new_merge_perspective(
206 &self,
207 left: Location,
208 right: Location,
209 last_common_ancestor: (Location, usize),
210 policy_id: PolicyId,
211 braid: Self::FactIndex,
212 ) -> Result<Option<Self::Perspective>, StorageError>;
213
214 fn get_segment(&self, location: Location) -> Result<Self::Segment, StorageError>;
216
217 fn get_head(&self) -> Result<Location, StorageError>;
219
220 fn commit(&mut self, segment: Self::Segment) -> Result<(), StorageError>;
223
224 fn write(&mut self, perspective: Self::Perspective) -> Result<Self::Segment, StorageError>;
226
227 fn write_facts(
229 &mut self,
230 fact_perspective: Self::FactPerspective,
231 ) -> Result<Self::FactIndex, StorageError>;
232
233 fn is_ancestor(
235 &self,
236 search_location: Location,
237 segment: &Self::Segment,
238 ) -> Result<bool, StorageError> {
239 let mut queue = Vec::new();
240 queue.extend(segment.prior());
241 let segment = self.get_segment(search_location)?;
242 let address = segment
243 .get_command(search_location)
244 .assume("location must exist")?
245 .address()?;
246 'outer: while let Some(location) = queue.pop() {
247 if location.segment == search_location.segment
248 && location.command >= search_location.command
249 {
250 return Ok(true);
251 }
252 let segment = self.get_segment(location)?;
253 if address.max_cut > segment.longest_max_cut()? {
254 continue;
255 }
256 for (skip, max_cut) in segment.skip_list() {
257 if max_cut >= &address.max_cut {
258 queue.push(*skip);
259 continue 'outer;
260 }
261 }
262 queue.extend(segment.prior());
263 }
264 Ok(false)
265 }
266}
267
268type MaxCut = usize;
269
270pub trait Segment {
280 type FactIndex: FactIndex;
281 type Command<'a>: Command
282 where
283 Self: 'a;
284
285 fn head(&self) -> Result<Self::Command<'_>, StorageError>;
287
288 fn first(&self) -> Self::Command<'_>;
290
291 fn head_location(&self) -> Location;
293
294 fn first_location(&self) -> Location;
296
297 fn contains(&self, location: Location) -> bool;
299
300 fn policy(&self) -> PolicyId;
302
303 fn prior(&self) -> Prior<Location>;
305
306 fn get_command(&self, location: Location) -> Option<Self::Command<'_>>;
308
309 fn get_from_max_cut(&self, max_cut: usize) -> Result<Option<Location>, StorageError>;
311
312 fn get_from(&self, location: Location) -> Vec<Self::Command<'_>>;
314
315 fn facts(&self) -> Result<Self::FactIndex, StorageError>;
317
318 fn contains_any<I>(&self, locations: I) -> bool
319 where
320 I: IntoIterator,
321 I::Item: AsRef<Location>,
322 {
323 locations
324 .into_iter()
325 .any(|loc| self.contains(*loc.as_ref()))
326 }
327
328 fn shortest_max_cut(&self) -> MaxCut;
332
333 fn longest_max_cut(&self) -> Result<MaxCut, StorageError>;
337
338 fn skip_list(&self) -> &[(Location, MaxCut)];
347}
348
349pub trait FactIndex: Query {}
351
352pub trait Perspective: FactPerspective {
355 fn policy(&self) -> PolicyId;
357
358 fn add_command(&mut self, command: &impl Command) -> Result<usize, StorageError>;
361
362 fn includes(&self, id: CommandId) -> bool;
364
365 fn head_address(&self) -> Result<Prior<Address>, Bug>;
367}
368
369pub trait FactPerspective: QueryMut {}
371
372pub trait Revertable {
375 fn checkpoint(&self) -> Checkpoint;
377
378 fn revert(&mut self, checkpoint: Checkpoint) -> Result<(), Bug>;
380}
381
382pub struct Checkpoint {
384 pub index: usize,
386}
387
388pub trait Query {
395 fn query(&self, name: &str, keys: &[Box<[u8]>]) -> Result<Option<Box<[u8]>>, StorageError>;
397
398 type QueryIterator: Iterator<Item = Result<Fact, StorageError>>;
400
401 fn query_prefix(
406 &self,
407 name: &str,
408 prefix: &[Box<[u8]>],
409 ) -> Result<Self::QueryIterator, StorageError>;
410}
411
412#[derive(Debug, PartialEq, Eq)]
414pub struct Fact {
415 pub key: Keys,
417 pub value: Box<[u8]>,
419}
420
421pub trait QueryMut: Query {
425 fn insert(&mut self, name: String, keys: Keys, value: Box<[u8]>);
429
430 fn delete(&mut self, name: String, keys: Keys);
432}
433
434#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
436pub struct Keys(Box<[Box<[u8]>]>);
437
438impl Deref for Keys {
439 type Target = [Box<[u8]>];
440 fn deref(&self) -> &[Box<[u8]>] {
441 self.0.as_ref()
442 }
443}
444
445impl AsRef<[Box<[u8]>]> for Keys {
446 fn as_ref(&self) -> &[Box<[u8]>] {
447 self.0.as_ref()
448 }
449}
450
451impl core::borrow::Borrow<[Box<[u8]>]> for Keys {
452 fn borrow(&self) -> &[Box<[u8]>] {
453 self.0.as_ref()
454 }
455}
456
457impl From<&[&[u8]]> for Keys {
458 fn from(value: &[&[u8]]) -> Self {
459 value.iter().copied().collect()
460 }
461}
462
463impl Keys {
464 fn starts_with(&self, prefix: &[Box<[u8]>]) -> bool {
465 self.as_ref().starts_with(prefix)
466 }
467}
468
469impl<B: Into<Box<[u8]>>> FromIterator<B> for Keys {
470 fn from_iter<T: IntoIterator<Item = B>>(iter: T) -> Self {
471 Self(iter.into_iter().map(Into::into).collect())
472 }
473}
474
475