willow-data-model 0.7.0

The core datatypes of Willow, an eventually consistent data store with improved distributed deletion.
Documentation
//! [Groupings](https://willowprotocol.org/specs/grouping-entries/) of entries in 3d space.
//!
//! This module implements the [groupings](https://willowprotocol.org/specs/grouping-entries/) used by the Willow specifications:
//!
//! - [ranges](https://willowprotocol.org/specs/grouping-entries/#ranges) ([`WillowRange`]),
//! - [3d ranges](https://willowprotocol.org/specs/grouping-entries/#D3Range) ([`Range3d`]),
//! - [areas](https://willowprotocol.org/specs/grouping-entries/#areas) ([`Area`]), and
//! - [areas of interest](https://willowprotocol.org/specs/grouping-entries/#aois) ([`AreaOfInterest`]).
//!
//! Our implementations center around two traits: [`Coordinatelike`] describes values which fall into some position in three-dimensional Willow space, and [`Grouping`] describes groupings of values based on their position in three-dimensional Willow space. The [`CoordinatelikeExt`] trait then provides convenient methods for checking which values are included in which groupings.
//!
//! ```
//! use willow_data_model::prelude::*;
//!
//! # #[cfg(feature = "dev")] {
//! let entry = Entry::builder()
//!     .namespace_id(Family)
//!     .subspace_id(Betty)
//!     .path(Path::<4, 4, 4>::new())
//!     .timestamp(12345)
//!     .payload_digest("some_hash")
//!     .payload_length(17)
//!     .build();
//!
//! assert!(entry.wdm_is_in(&Range3d::full()));
//! # }
//! ```

use core::fmt;

#[cfg(feature = "dev")]
use arbitrary::Arbitrary;

use crate::prelude::*;

mod willow_range;
pub use willow_range::*;

mod range_3d;
pub use range_3d::*;

mod area;
pub use area::*;

mod area_of_interest;
pub use area_of_interest::*;

mod keylike;
pub use keylike::*;

mod coordinatelike;
pub use coordinatelike::*;

mod namespaced;
pub use namespaced::*;

pub mod private_interest;

/// A [`WillowRange`] of [SubspaceIds](https://willowprotocol.org/specs/data-model/index.html#SubspaceId).
///
/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#SubspaceRange)
pub type SubspaceRange<S> = WillowRange<S>;

/// A [`WillowRange`] of [Paths](https://willowprotocol.org/specs/data-model/index.html#Path).
///
/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#PathRange)
pub type PathRange<const MCL: usize, const MCC: usize, const MPL: usize> =
    WillowRange<Path<MCL, MCC, MPL>>;

/// A [`WillowRange`] of [Timestamps](https://willowprotocol.org/specs/data-model/index.html#Timestamp).
///
/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#TimeRange)
pub type TimeRange = WillowRange<Timestamp>;

/// An error returned whenever an operation would result in an empty grouping.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
pub struct EmptyGrouping;

impl fmt::Display for EmptyGrouping {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "An operation would have resulted in an empty grouping of Willow entries."
        )
    }
}

impl core::error::Error for EmptyGrouping {}

/// A grouping of entries.
///
/// A grouping describes a non-empty set of [`Coordinatelike`] values, with [`Grouping::wdm_includes`] providing the membership test. Groupings must implement [`PartialOrd`] as the subset relation.
pub trait Grouping<const MCL: usize, const MCC: usize, const MPL: usize, S>:
    PartialOrd + Sized
{
    /// Returns `true` iff the given [`Coordinatelike`] value is included in this grouping.
    fn wdm_includes<Coord>(&self, coord: &Coord) -> bool
    where
        Coord: Coordinatelike<MCL, MCC, MPL, S> + ?Sized;

    /// Returns `true` iff every value [included](Grouping::wdm_includes) in `other` is also [included](Grouping::wdm_includes) in `self`.
    fn wdm_includes_grouping(&self, other: &Self) -> bool {
        self >= other
    }

    /// Returns `true` iff every value [included](Grouping::wdm_includes) in `other` is also [included](Grouping::wdm_includes) in `self` *and* `self` and `other` are not equal.
    fn wdm_strictly_includes_grouping(&self, other: &Self) -> bool {
        self > other
    }

    /// Returns a grouping which [includes](Grouping::wdm_includes) exactly those values [included](Grouping::wdm_includes) by both `self` and `other`. If that set would be empty, returns an [`EmptyGrouping`] error instead.
    fn wdm_intersection(&self, other: &Self) -> Result<Self, EmptyGrouping>
    where
        S: Clone;

    /// Returns `true` iff the given [`Coordinatelike`] value is [included](Grouping::wdm_includes) in both `self` and `other`.
    fn wdm_includes_in_intersection<Coord>(&self, other: &Self, coord: &Coord) -> bool
    where
        Coord: Coordinatelike<MCL, MCC, MPL, S> + ?Sized,
    {
        self.wdm_includes(coord) && other.wdm_includes(coord)
    }
}

/// Returns `true` if the outer `Option<S>` includes the inner `Option<S>`, where `None` denotes interest in all subspaces of the namespace.
pub fn subspace_includes_subspace<S: PartialEq>(outer: Option<&S>, inner: Option<&S>) -> bool {
    match (outer, inner) {
        (Some(s1), Some(s2)) => s1 == s2,
        (Some(_), None) => false,
        _ => true,
    }
}