willow_data_model/groupings/coordinatelike.rs
1use crate::prelude::*;
2
3/// A coordinatelike value represents a point in the [three-dimensional willow space](https://willowprotocol.org/specs/grouping-entries/index.html#D3Range) (within a given [namespace](https://willowprotocol.org/specs/data-model/index.html#namespace)).
4///
5/// This trait does not include the namespace id, because our implementation separates entry storage by namespace from the get-go.
6pub trait Coordinatelike<const MCL: usize, const MCC: usize, const MPL: usize, S>:
7 Keylike<MCL, MCC, MPL, S>
8{
9 /// Returns the [timestamp](https://willowprotocol.org/specs/data-model/index.html#entry_timestamp) of `self`.
10 fn wdm_timestamp(&self) -> Timestamp;
11}
12
13impl<const MCL: usize, const MCC: usize, const MPL: usize, S> Keylike<MCL, MCC, MPL, S>
14 for (S, Path<MCL, MCC, MPL>, Timestamp)
15{
16 fn wdm_subspace_id(&self) -> &S {
17 &self.0
18 }
19
20 fn wdm_path(&self) -> &Path<MCL, MCC, MPL> {
21 &self.1
22 }
23}
24
25impl<const MCL: usize, const MCC: usize, const MPL: usize, S> Coordinatelike<MCL, MCC, MPL, S>
26 for (S, Path<MCL, MCC, MPL>, Timestamp)
27{
28 fn wdm_timestamp(&self) -> Timestamp {
29 self.2
30 }
31}
32
33/// Methods for working with [`Coordinatelikes`](Coordinatelike).
34///
35/// This trait is automatically implemented by all types implementing [`Coordinatelike`].
36pub trait CoordinatelikeExt<const MCL: usize, const MCC: usize, const MPL: usize, S>:
37 Coordinatelike<MCL, MCC, MPL, S> + KeylikeExt<MCL, MCC, MPL, S>
38{
39 /// Returns whether `self` and `other` describe equal coordinates, i.e., whether their [subspace ids](Keylike::wdm_subspace_id), [paths](Keylike::wdm_path), and [timestamps](Coordinatelike::wdm_timestamp) are all equal.
40 ///
41 /// # Examples
42 ///
43 /// ```
44 /// use willow_data_model::prelude::*;
45 ///
46 /// assert!(
47 /// ([7; 32], Path::<4, 4, 4>::new(), 25.into())
48 /// .wdm_coordinate_eq(&([7; 32], Path::<4, 4, 4>::new(), 25.into()))
49 /// );
50 /// assert!(
51 /// !([7; 32], Path::<4, 4, 4>::new(), 25.into())
52 /// .wdm_coordinate_eq(&([8; 32], Path::<4, 4, 4>::new(), 25.into()))
53 /// );
54 /// ```
55 fn wdm_coordinate_eq<OtherCoordinate>(&self, other: &OtherCoordinate) -> bool
56 where
57 OtherCoordinate: Coordinatelike<MCL, MCC, MPL, S>,
58 S: PartialEq,
59 {
60 self.wdm_key_eq(other) && self.wdm_timestamp() == other.wdm_timestamp()
61 }
62
63 /// Returns whether `self` and `other` describe non-equal coordinates, i.e., whether their [subspace ids](Keylike::wdm_subspace_id), [paths](Keylike::wdm_path), and [timestamps](Coordinatelike::wdm_timestamp) are not all equal.
64 ///
65 /// # Examples
66 ///
67 /// ```
68 /// use willow_data_model::prelude::*;
69 ///
70 /// assert!(
71 /// !([7; 32], Path::<4, 4, 4>::new(), 25.into())
72 /// .wdm_coordinate_ne(&([7; 32], Path::<4, 4, 4>::new(), 25.into()))
73 /// );
74 /// assert!(
75 /// ([7; 32], Path::<4, 4, 4>::new(), 25.into())
76 /// .wdm_coordinate_ne(&([8; 32], Path::<4, 4, 4>::new(), 25.into()))
77 /// );
78 /// ```
79 fn wdm_coordinate_ne<OtherCoordinate>(&self, other: &OtherCoordinate) -> bool
80 where
81 OtherCoordinate: Coordinatelike<MCL, MCC, MPL, S>,
82 S: PartialEq,
83 {
84 self.wdm_key_ne(other) || self.wdm_timestamp() != other.wdm_timestamp()
85 }
86
87 /// Returns whether `self` is included in the given [`Grouping`].
88 ///
89 /// ```
90 /// use willow_data_model::prelude::*;
91 ///
92 /// assert!(
93 /// ([7; 32], Path::<4, 4, 4>::new(), 8.into())
94 /// .wdm_is_in(
95 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., ..Timestamp::from(17))
96 /// )
97 /// );
98 /// assert!(
99 /// !([7; 32], Path::<4, 4, 4>::new(), 52.into())
100 /// .wdm_is_in(
101 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., ..Timestamp::from(17))
102 /// )
103 /// );
104 /// ```
105 fn wdm_is_in<G>(&self, grouping: &G) -> bool
106 where
107 G: Grouping<MCL, MCC, MPL, S>,
108 {
109 grouping.wdm_includes(self)
110 }
111
112 /// Returns whether `self` is included in the intersection of the two given [`Groupings`](Grouping).
113 ///
114 /// ```
115 /// use willow_data_model::prelude::*;
116 ///
117 /// assert!(
118 /// ([7; 32], Path::<4, 4, 4>::new(), 25.into())
119 /// .wdm_is_in_intersection(
120 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., Timestamp::from(17)..),
121 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., ..Timestamp::from(28)),
122 /// )
123 /// );
124 /// assert!(
125 /// !([7; 32], Path::<4, 4, 4>::new(), 30.into())
126 /// .wdm_is_in_intersection(
127 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., Timestamp::from(17)..),
128 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., ..Timestamp::from(28)),
129 /// )
130 /// );
131 /// assert!(
132 /// !([7; 32], Path::<4, 4, 4>::new(), 14.into())
133 /// .wdm_is_in_intersection(
134 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., Timestamp::from(17)..),
135 /// &Range3d::<4, 4, 4, [u8; 32]>::new([7; 32].., .., ..Timestamp::from(28)),
136 /// )
137 /// );
138 /// ```
139 fn wdm_is_in_intersection<G>(&self, grouping1: &G, grouping2: &G) -> bool
140 where
141 G: Grouping<MCL, MCC, MPL, S>,
142 {
143 grouping1.wdm_includes_in_intersection(grouping2, self)
144 }
145}
146
147impl<const MCL: usize, const MCC: usize, const MPL: usize, S, T> CoordinatelikeExt<MCL, MCC, MPL, S>
148 for T
149where
150 T: Coordinatelike<MCL, MCC, MPL, S>,
151{
152}