Onset: version control where nobody waits and nothing gets lost. The on command, its core and onset-server.
| 6 | //! hosted server in Wasm) own storage and the network; everything here works |
| 7 | //! on bytes and on a [`Source`] that hands objects back by ID. |
| 8 |
| 9 | pub mod bundle; |
| 10 | pub mod chunk; |
| 11 | pub mod diff; |
| 12 | pub mod filter; |
| 13 | pub mod id; |
| 14 | pub mod merge; |
| 15 | pub mod object; |
| 16 | pub mod secrets; |
| 17 | pub mod tree; |
| 18 | pub mod version; |
| 19 |
| 20 | pub use id::Id; |
| 21 | pub use object::{Kind, Object}; |
| 22 |
| 23 | #[derive(Debug, thiserror::Error)] |
| 24 | pub enum Error { |
| 25 | #[error("missing object {0}")] |
| 26 | Missing(Id), |
| 27 | #[error("{0}")] |
| 28 | Corrupt(String), |
| 29 | #[error("limit exceeded: {0}")] |
| 30 | Limit(String), |
| 31 | } |
| 32 |
| 33 | pub type Result<T, E = Error> = std::result::Result<T, E>; |
| 34 |
| 35 | pub(crate) fn corrupt(message: impl Into<String>) -> Error { |
| 36 | Error::Corrupt(message.into()) |
| 37 | } |
| 38 |
| 39 | /// Where objects come from. Hosts implement it over their storage. |
| 40 | pub trait Source { |
| 41 | fn get(&self, id: &Id) -> Result<Option<Object>>; |
| 42 |
| 43 | fn must(&self, id: &Id) -> Result<Object> { |
| 44 | self.get(id)?.ok_or(Error::Missing(*id)) |
| 45 | } |
| 46 | } |
| 47 |
| 48 | /// An in-memory source, for tests and for objects a merge creates. |
| 49 | #[derive(Default, Clone)] |
| 50 | pub struct MemSource { |
| 51 | pub objects: std::collections::HashMap<Id, Object>, |
| 52 | } |
| 53 |
| 54 | impl MemSource { |
| 55 | pub fn put(&mut self, object: Object) -> Id { |
| 56 | let id = object.id(); |
| 57 | self.objects.insert(id, object); |
| 58 | id |
| 59 | } |
| 60 | } |
| 61 |
| 62 | impl Source for MemSource { |
| 63 | fn get(&self, id: &Id) -> Result<Option<Object>> { |
| 64 | Ok(self.objects.get(id).cloned()) |
| 65 | } |
| 66 | } |
| 67 |
| 68 | /// Reads from `first`, then `second` (new objects over a store). |
| 69 | pub struct Layered<'a> { |
| 70 | pub first: &'a dyn Source, |
| 71 | pub second: &'a dyn Source, |
| 72 | } |
| 73 |
| 74 | impl Source for Layered<'_> { |
| 75 | fn get(&self, id: &Id) -> Result<Option<Object>> { |
| 76 | match self.first.get(id)? { |
| 77 | Some(o) => Ok(Some(o)), |
| 78 | None => self.second.get(id), |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 |