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 remove_storage(&mut self, graph: GraphId) -> Result<(), StorageError>;
144
145 fn list_graph_ids(
148 &mut self,
149 ) -> Result<impl Iterator<Item = Result<GraphId, StorageError>>, StorageError>;
150}
151
152pub trait Storage {
155 type Perspective: Perspective + Revertable;
156 type FactPerspective: FactPerspective;
157 type Segment: Segment<FactIndex = Self::FactIndex>;
158 type FactIndex: FactIndex;
159
160 fn get_location(&self, address: Address) -> Result<Option<Location>, StorageError> {
163 self.get_location_from(self.get_head()?, address)
164 }
165
166 fn get_location_from(
168 &self,
169 start: Location,
170 address: Address,
171 ) -> Result<Option<Location>, StorageError> {
172 let mut queue = Vec::new();
173 queue.push(start);
174 'outer: while let Some(loc) = queue.pop() {
175 let head = self.get_segment(loc)?;
176 if address.max_cut > head.longest_max_cut()? {
177 continue;
178 }
179 if let Some(loc) = head.get_from_max_cut(address.max_cut)? {
180 let command = head.get_command(loc).assume("command must exist")?;
181 if command.id() == address.id {
182 return Ok(Some(loc));
183 }
184 }
185 for (skip, max_cut) in head.skip_list() {
188 if max_cut >= &address.max_cut {
189 queue.push(*skip);
190 continue 'outer;
191 }
192 }
193 queue.extend(head.prior());
194 }
195 Ok(None)
196 }
197
198 fn get_command_id(&self, location: Location) -> Result<CommandId, StorageError>;
200
201 fn get_linear_perspective(
203 &self,
204 parent: Location,
205 ) -> Result<Option<Self::Perspective>, StorageError>;
206
207 fn get_fact_perspective(&self, first: Location) -> Result<Self::FactPerspective, StorageError>;
210
211 fn new_merge_perspective(
213 &self,
214 left: Location,
215 right: Location,
216 last_common_ancestor: (Location, usize),
217 policy_id: PolicyId,
218 braid: Self::FactIndex,
219 ) -> Result<Option<Self::Perspective>, StorageError>;
220
221 fn get_segment(&self, location: Location) -> Result<Self::Segment, StorageError>;
223
224 fn get_head(&self) -> Result<Location, StorageError>;
226
227 fn commit(&mut self, segment: Self::Segment) -> Result<(), StorageError>;
230
231 fn write(&mut self, perspective: Self::Perspective) -> Result<Self::Segment, StorageError>;
233
234 fn write_facts(
236 &mut self,
237 fact_perspective: Self::FactPerspective,
238 ) -> Result<Self::FactIndex, StorageError>;
239
240 fn is_ancestor(
242 &self,
243 search_location: Location,
244 segment: &Self::Segment,
245 ) -> Result<bool, StorageError> {
246 let mut queue = Vec::new();
247 queue.extend(segment.prior());
248 let segment = self.get_segment(search_location)?;
249 let address = segment
250 .get_command(search_location)
251 .assume("location must exist")?
252 .address()?;
253 'outer: while let Some(location) = queue.pop() {
254 if location.segment == search_location.segment
255 && location.command >= search_location.command
256 {
257 return Ok(true);
258 }
259 let segment = self.get_segment(location)?;
260 if address.max_cut > segment.longest_max_cut()? {
261 continue;
262 }
263 for (skip, max_cut) in segment.skip_list() {
264 if max_cut >= &address.max_cut {
265 queue.push(*skip);
266 continue 'outer;
267 }
268 }
269 queue.extend(segment.prior());
270 }
271 Ok(false)
272 }
273}
274
275type MaxCut = usize;
276
277pub trait Segment {
287 type FactIndex: FactIndex;
288 type Command<'a>: Command
289 where
290 Self: 'a;
291
292 fn head(&self) -> Result<Self::Command<'_>, StorageError>;
294
295 fn first(&self) -> Self::Command<'_>;
297
298 fn head_location(&self) -> Location;
300
301 fn first_location(&self) -> Location;
303
304 fn contains(&self, location: Location) -> bool;
306
307 fn policy(&self) -> PolicyId;
309
310 fn prior(&self) -> Prior<Location>;
312
313 fn get_command(&self, location: Location) -> Option<Self::Command<'_>>;
315
316 fn get_from_max_cut(&self, max_cut: usize) -> Result<Option<Location>, StorageError>;
318
319 fn get_from(&self, location: Location) -> Vec<Self::Command<'_>>;
321
322 fn facts(&self) -> Result<Self::FactIndex, StorageError>;
324
325 fn contains_any<I>(&self, locations: I) -> bool
326 where
327 I: IntoIterator,
328 I::Item: AsRef<Location>,
329 {
330 locations
331 .into_iter()
332 .any(|loc| self.contains(*loc.as_ref()))
333 }
334
335 fn shortest_max_cut(&self) -> MaxCut;
339
340 fn longest_max_cut(&self) -> Result<MaxCut, StorageError>;
344
345 fn skip_list(&self) -> &[(Location, MaxCut)];
354}
355
356pub trait FactIndex: Query {}
358
359pub trait Perspective: FactPerspective {
362 fn policy(&self) -> PolicyId;
364
365 fn add_command(&mut self, command: &impl Command) -> Result<usize, StorageError>;
368
369 fn includes(&self, id: CommandId) -> bool;
371
372 fn head_address(&self) -> Result<Prior<Address>, Bug>;
374}
375
376pub trait FactPerspective: QueryMut {}
378
379pub trait Revertable {
382 fn checkpoint(&self) -> Checkpoint;
384
385 fn revert(&mut self, checkpoint: Checkpoint) -> Result<(), Bug>;
387}
388
389pub struct Checkpoint {
391 pub index: usize,
393}
394
395pub trait Query {
402 fn query(&self, name: &str, keys: &[Box<[u8]>]) -> Result<Option<Box<[u8]>>, StorageError>;
404
405 type QueryIterator: Iterator<Item = Result<Fact, StorageError>>;
407
408 fn query_prefix(
413 &self,
414 name: &str,
415 prefix: &[Box<[u8]>],
416 ) -> Result<Self::QueryIterator, StorageError>;
417}
418
419#[derive(Debug, PartialEq, Eq)]
421pub struct Fact {
422 pub key: Keys,
424 pub value: Box<[u8]>,
426}
427
428pub trait QueryMut: Query {
432 fn insert(&mut self, name: String, keys: Keys, value: Box<[u8]>);
436
437 fn delete(&mut self, name: String, keys: Keys);
439}
440
441#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
443pub struct Keys(Box<[Box<[u8]>]>);
444
445impl Deref for Keys {
446 type Target = [Box<[u8]>];
447 fn deref(&self) -> &[Box<[u8]>] {
448 self.0.as_ref()
449 }
450}
451
452impl AsRef<[Box<[u8]>]> for Keys {
453 fn as_ref(&self) -> &[Box<[u8]>] {
454 self.0.as_ref()
455 }
456}
457
458impl core::borrow::Borrow<[Box<[u8]>]> for Keys {
459 fn borrow(&self) -> &[Box<[u8]>] {
460 self.0.as_ref()
461 }
462}
463
464impl From<&[&[u8]]> for Keys {
465 fn from(value: &[&[u8]]) -> Self {
466 value.iter().copied().collect()
467 }
468}
469
470impl Keys {
471 fn starts_with(&self, prefix: &[Box<[u8]>]) -> bool {
472 self.as_ref().starts_with(prefix)
473 }
474}
475
476impl<B: Into<Box<[u8]>>> FromIterator<B> for Keys {
477 fn from_iter<T: IntoIterator<Item = B>>(iter: T) -> Self {
478 Self(iter.into_iter().map(Into::into).collect())
479 }
480}
481
482