willow_data_model/groupings/
mod.rs

1//! [Groupings](https://willowprotocol.org/specs/grouping-entries/) of entries in 3d space.
2//!
3//! This module implements the [groupings](https://willowprotocol.org/specs/grouping-entries/) used by the Willow specifications:
4//!
5//! - [ranges](https://willowprotocol.org/specs/grouping-entries/#ranges) ([`WillowRange`]),
6//! - [3d ranges](https://willowprotocol.org/specs/grouping-entries/#D3Range) ([`Range3d`]),
7//! - [areas](https://willowprotocol.org/specs/grouping-entries/#areas) ([`Area`]), and
8//! - [areas of interest](https://willowprotocol.org/specs/grouping-entries/#aois) ([`AreaOfInterest`]).
9//!
10//! 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.
11//!
12//! ```
13//! use willow_data_model::prelude::*;
14//!
15//! # #[cfg(feature = "dev")] {
16//! let entry = Entry::builder()
17//!     .namespace_id(Family)
18//!     .subspace_id(Betty)
19//!     .path(Path::<4, 4, 4>::new())
20//!     .timestamp(12345)
21//!     .payload_digest("some_hash")
22//!     .payload_length(17)
23//!     .build().unwrap();
24//!
25//! assert!(entry.wdm_is_in(&Range3d::full()));
26//! # }
27//! ```
28
29use core::fmt;
30
31#[cfg(feature = "dev")]
32use arbitrary::Arbitrary;
33
34use crate::prelude::*;
35
36mod willow_range;
37pub use willow_range::*;
38
39mod range_3d;
40pub use range_3d::*;
41
42mod area;
43pub use area::*;
44
45mod area_of_interest;
46pub use area_of_interest::*;
47
48mod keylike;
49pub use keylike::*;
50
51mod coordinatelike;
52pub use coordinatelike::*;
53
54mod namespaced;
55pub use namespaced::*;
56
57/// A [`WillowRange`] of [SubspaceIds](https://willowprotocol.org/specs/data-model/index.html#SubspaceId).
58///
59/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#SubspaceRange)
60pub type SubspaceRange<S> = WillowRange<S>;
61
62/// A [`WillowRange`] of [Paths](https://willowprotocol.org/specs/data-model/index.html#Path).
63///
64/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#PathRange)
65pub type PathRange<const MCL: usize, const MCC: usize, const MPL: usize> =
66    WillowRange<Path<MCL, MCC, MPL>>;
67
68/// A [`WillowRange`] of [Timestamps](https://willowprotocol.org/specs/data-model/index.html#Timestamp).
69///
70/// [Specification](https://willowprotocol.org/specs/grouping-entries/index.html#TimeRange)
71pub type TimeRange = WillowRange<Timestamp>;
72
73/// An error returned whenever an operation would result in an empty grouping.
74#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
75#[cfg_attr(feature = "dev", derive(Arbitrary))]
76pub struct EmptyGrouping;
77
78impl fmt::Display for EmptyGrouping {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        write!(
81            f,
82            "An operation would have resulted in an empty grouping of Willow entries."
83        )
84    }
85}
86
87impl core::error::Error for EmptyGrouping {}
88
89/// A grouping of entries.
90///
91/// 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.
92pub trait Grouping<const MCL: usize, const MCC: usize, const MPL: usize, S>:
93    PartialOrd + Sized
94{
95    /// Returns `true` iff the given [`Coordinatelike`] value is included in this grouping.
96    fn wdm_includes<Coord>(&self, coord: &Coord) -> bool
97    where
98        Coord: Coordinatelike<MCL, MCC, MPL, S> + ?Sized;
99
100    /// Returns `true` iff every value [included](Grouping::wdm_includes) in `other` is also [included](Grouping::wdm_includes) in `self`.
101    fn wdm_includes_grouping(&self, other: &Self) -> bool {
102        self >= other
103    }
104
105    /// 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.
106    fn wdm_strictly_includes_grouping(&self, other: &Self) -> bool {
107        self > other
108    }
109
110    /// 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.
111    fn wdm_intersection(&self, other: &Self) -> Result<Self, EmptyGrouping>
112    where
113        S: Clone;
114
115    /// Returns `true` iff the given [`Coordinatelike`] value is [included](Grouping::wdm_includes) in both `self` and `other`.
116    fn wdm_includes_in_intersection<Coord>(&self, other: &Self, coord: &Coord) -> bool
117    where
118        Coord: Coordinatelike<MCL, MCC, MPL, S> + ?Sized,
119    {
120        self.wdm_includes(coord) && other.wdm_includes(coord)
121    }
122}