#![forbid(unsafe_code)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
use futures_util::TryStreamExt;
use object_rainbow::{
Equivalent, Fetch, Inline, InlineOutput, ListHashes, MaybeHasNiche, Object, Parse, ParseInline,
Size, Tagged, ToOutput, Topological, Traversible, assert_impl, derive_for_wrapped,
};
use object_rainbow_chain_tree::ChainTree;
use object_rainbow_point::Point;
pub mod enforce_unique;
#[cfg(feature = "hamt")]
mod hamt;
pub mod hashed;
pub mod remap;
pub mod skip;
#[cfg(feature = "trie")]
mod trie;
#[cfg(feature = "unique-diffs")]
pub mod unique_diffs;
#[derive(
ToOutput, InlineOutput, Tagged, ListHashes, Topological, Parse, ParseInline, Size, MaybeHasNiche,
)]
pub struct History<T, D>(ChainTree<(T, D)>);
assert_impl!(
impl<T, D, E> Inline<E> for History<T, D>
where
E: 'static + Send + Sync + Clone,
T: Inline<E>,
D: Object<E>,
{
}
);
impl<T, D> Clone for History<T, D> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T, D> History<T, D> {
pub const ROOT: Self = Self(ChainTree::EMPTY);
}
impl<T, D> Default for History<T, D> {
fn default() -> Self {
Self(Default::default())
}
}
impl<T, D> History<T, D> {
pub const fn new() -> Self {
Self::ROOT
}
}
#[derive_for_wrapped]
pub trait Apply<Diff: Send>: Send {
type Output: Send;
fn apply(
&mut self,
diff: Diff,
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>>;
}
impl<T: Clone + Traversible + InlineOutput + Default + Apply<D>, D: Clone + Traversible>
History<T, D>
{
pub async fn commit(&mut self, diff: D) -> object_rainbow::Result<()> {
let mut tree = self.tree().await?;
let hash = tree.full_hash();
tree.apply(diff.clone()).await?;
if hash != tree.full_hash() {
self.0.push((tree, diff)).await?;
}
Ok(())
}
pub async fn check_forward(&self, other: &Self) -> object_rainbow::Result<()> {
other
.0
.diff(&self.0)
.and_then(async |node| {
let diff = node.value().1.clone();
let mut tree = node
.prev()
.last()
.await?
.map(|(tree, _)| tree)
.unwrap_or_default();
let hash = tree.full_hash();
tree.apply(diff).await?;
let new_hash = tree.full_hash();
if new_hash == hash {
Err(object_rainbow::error_consistency!("noop diff"))
} else if new_hash == node.value().0.full_hash() {
Ok(())
} else {
Err(object_rainbow::error_consistency!(
"diff doesn't match the new tree",
))
}
})
.try_collect()
.await
}
pub async fn forward(&mut self, other: Self) -> object_rainbow::Result<()> {
self.check_forward(&other).await?;
self.forward(other).await
}
pub async fn tree(&self) -> object_rainbow::Result<T> {
Ok(self
.0
.last()
.await?
.map(|(tree, _)| tree)
.unwrap_or_default())
}
pub async fn rebase(&mut self, base: &Self) -> object_rainbow::Result<()> {
let mut base = base.clone();
base.rebase_other(self).await?;
*self = base;
Ok(())
}
pub async fn rebase_other(&mut self, other: &Self) -> object_rainbow::Result<()> {
let common_ancestor = self.0.common_ancestor(&[&other.0]).await?;
let diff = other
.0
.diff_backwards(&common_ancestor)
.map_ok(|node| node.value().1.clone())
.try_collect::<Vec<_>>()
.await?;
for diff in diff.into_iter().rev() {
self.commit(diff).await?;
}
Ok(())
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
)]
pub struct FromIter<T>(pub T);
impl<T: Apply<D>, D: Send, I: Send + IntoIterator<Item = D, IntoIter: Send>> Apply<I>
for FromIter<T>
{
type Output = Vec<T::Output>;
async fn apply(&mut self, diff: I) -> object_rainbow::Result<Self::Output> {
let mut output = Vec::new();
for diff in diff {
output.push(self.0.apply(diff).await?);
}
Ok(output)
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Default,
)]
pub struct Points<T>(pub T);
impl<T: Apply<D>, D: Send + Traversible> Apply<Point<D>> for Points<T> {
type Output = T::Output;
async fn apply(&mut self, diff: Point<D>) -> object_rainbow::Result<Self::Output> {
self.0.apply(diff.fetch().await?).await
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct DiscardHeader<T>(pub T);
assert_impl!(
impl<T, E> Inline<E> for DiscardHeader<T>
where
T: Inline<E>,
E: 'static + Send + Sync + Clone,
{
}
);
impl<T: Apply<D>, D: Send, H: Send> Apply<(H, D)> for DiscardHeader<T> {
type Output = T::Output;
fn apply(
&mut self,
(_, diff): (H, D),
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
self.0.apply(diff)
}
}
impl<T> Equivalent<T> for DiscardHeader<T> {
fn into_equivalent(self) -> T {
self.0
}
fn from_equivalent(tree: T) -> Self {
Self(tree)
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct Sequential<First, Second> {
first: First,
second: Second,
}
impl<First, Second> Sequential<First, Second> {
pub fn first(&self) -> &First {
&self.first
}
pub fn second(&self) -> &Second {
&self.second
}
}
impl<Diff: Send, First: Apply<Diff>, Second: Apply<First::Output>> Apply<Diff>
for Sequential<First, Second>
{
type Output = Second::Output;
fn apply(
&mut self,
diff: Diff,
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
async move { self.second.apply(self.first.apply(diff).await?).await }
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct Parallel<A, B> {
a: A,
b: B,
}
impl<A, B> Parallel<A, B> {
pub fn a(&self) -> &A {
&self.a
}
pub fn b(&self) -> &B {
&self.b
}
}
impl<Diff: Send + Clone, A: Apply<Diff>, B: Apply<Diff>> Apply<Diff> for Parallel<A, B> {
type Output = (A::Output, B::Output);
fn apply(
&mut self,
diff: Diff,
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::try_join(self.a.apply(diff.clone()), self.b.apply(diff))
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct Discard;
impl<D: Send> Apply<D> for Discard {
type Output = ();
fn apply(&mut self, _: D) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::ready(Ok(()))
}
}
impl Apply<()> for () {
type Output = ();
fn apply(
&mut self,
(): (),
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::ready(Ok(()))
}
}
impl<A: Apply<DiffA>, B: Apply<DiffB>, DiffA: Send, DiffB: Send> Apply<(DiffA, DiffB)> for (A, B) {
type Output = (A::Output, B::Output);
fn apply(
&mut self,
(a, b): (DiffA, DiffB),
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::try_join(self.0.apply(a), self.1.apply(b))
}
}
impl<T: Clone + Traversible + Apply<D>, D: Send> Apply<D> for Point<T> {
type Output = T::Output;
async fn apply(&mut self, diff: D) -> object_rainbow::Result<Self::Output> {
self.fetch_mut().await?.apply(diff).await
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct Return;
impl<D: Send> Apply<D> for Return {
type Output = D;
fn apply(
&mut self,
diff: D,
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::ready(Ok(diff))
}
}
#[derive(
Debug,
ToOutput,
InlineOutput,
Tagged,
ListHashes,
Topological,
Parse,
ParseInline,
Size,
MaybeHasNiche,
Clone,
Copy,
PartialEq,
Eq,
Default,
)]
pub struct Swap;
impl<A: Send, B: Send> Apply<(A, B)> for Swap {
type Output = (B, A);
fn apply(
&mut self,
(a, b): (A, B),
) -> impl Send + Future<Output = object_rainbow::Result<Self::Output>> {
futures_util::future::ready(Ok((b, a)))
}
}