1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! Provides abstractions for [privately encoding areas relative to other areas](https://willowprotocol.org/specs/encodings/index.html#enc_private_areas) and [private interests](https://willowprotocol.org/specs/pio/index.html#pio_private_interests).
//!
//! You probably don't need to interact with this unless you are building your own private encoding scheme.
use core::fmt;
use crate::prelude::*;
use ufotofu::{
codec::Blame,
codec_prelude::{RelativeDecodable, RelativeEncodable},
};
use willow_data_model::groupings::private_interest::{
AreaNotAlmostIncludedError, PrivateAreaContext as PrivateAreaContextGeneric,
PrivateInterest as PrivateInterestGeneric,
};
wrapper! {
/// Confidential data that relates to determining the [`AreaOfInterest`] that peers might be interested in synchronising.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
PrivateInterest;
PrivateInterestGeneric<MCL, MCC, MPL, NamespaceId, SubspaceId>
}
impl fmt::Debug for PrivateInterest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl PrivateInterest {
/// Returns a new [`PrivateInterest`] with the gives attributes.
pub fn new(namespace_id: NamespaceId, subspace_id: Option<SubspaceId>, path: Path) -> Self {
Self(PrivateInterestGeneric::new(
namespace_id,
subspace_id,
path.into(),
))
}
/// Returns the Namespace ID of this [`PrivateInterest`].
pub fn namespace(&self) -> &NamespaceId {
self.0.namespace()
}
/// Returns the specific SubspaceId of this [`PrivateInterest`], if present. `None` denotes interest in all subspaces of the namespace.
pub fn subspace(&self) -> Option<&SubspaceId> {
self.0.subspace()
}
/// Returns the path of this [`PrivateInterest`].
pub fn path(&self) -> &Path {
<&willow_data_model::paths::Path<MCL, MCC, MPL> as Into<&Path>>::into(self.0.path())
}
/// Returns `true` is this [`PrivateInterest`] is [more specific](https://willowprotocol.org/specs/pio/index.html#pi_more_specific) than `other`.
pub fn is_more_specific(&self, other: &Self) -> bool {
self.0.is_more_specific(other.into())
}
/// Returns `true` is this [`PrivateInterest`] is [disjoint](https://willowprotocol.org/specs/pio/index.html#pi_disjoint) from `other`, namely that there is no [`Entry`] which can be included in both.
pub fn is_disjoint(&self, other: &Self) -> bool {
self.0.is_disjoint(other.into())
}
/// Returns `true` is this [`PrivateInterest`] is [less specific](https://willowprotocol.org/specs/pio/index.html#pi_less_specific) than `other`.
pub fn is_less_specific(&self, other: &Self) -> bool {
self.0.is_less_specific(other.into())
}
/// Returns `true` is this [`PrivateInterest`] is [comparable](https://willowprotocol.org/specs/pio/index.html#pi_comparable) to `other`.
pub fn is_comparable(&self, other: &Self) -> bool {
self.0.is_comparable(other.into())
}
/// Returns true if `self` and `other` are [awkward](https://willowprotocol.org/specs/pio/index.html#pi_awkward), meaning they are neither [comparable](https://willowprotocol.org/specs/pio/index.html#pi_comparable) nor [disjoint](https://willowprotocol.org/specs/pio/index.html#pi_disjoint).
pub fn are_awkward(&self, other: &Self) -> bool {
self.0.are_awkward(other.into())
}
/// Returns `true` if the given [`Entry`] is [included](https://willowprotocol.org/specs/pio/index.html#pi_include_entry) by `self`.
pub fn includes_entry<PD>(&self, entry: &Entry) -> bool {
self.0.includes_entry(entry.into())
}
/// Returns `true` if the given [`Area`] in [included](https://willowprotocol.org/specs/pio/index.html#pi_include_area) by `self`.
pub fn includes_area(&self, area: &Area) -> bool {
self.0.includes_area(area.into())
}
/// Returns `true` if the given [`Area`] is related to `self`, that is:
///
/// - the path of `self` and the path of the `area` are [related](Path::is_related_to), and
/// - either `self.subspace()` is `None` or `self.subspace() == area.subspace()`.
pub fn is_related_to_area(&self, area: &Area) -> bool {
self.0.includes_area(area.into())
}
/// Returns `true` if `self` [almost includes](https://willowprotocol.org/specs/encodings/index.html#almost_include) the given [`Area`].
pub fn almost_includes_area(&self, area: &Area) -> bool {
self.0.almost_includes_area(area.into())
}
/// Clones self, but replaces the subspace id with `None`.
pub fn relax(&self) -> Self {
self.0.relax().into()
}
}
wrapper! {
/// The immutable [`PrivateAreaContext`](https://willowprotocol.org/specs/encodings/index.html#PrivateAreaContext) necessary to privately encode an [`Area`] relative to another [`Area`] which [almost includes](https://willowprotocol.org/specs/encodings/index.html#pi_amost_include) it.
#[derive(Clone, PartialEq, Eq, PartialOrd, Hash)]
PrivateAreaContext; PrivateAreaContextGeneric<MCL, MCC, MPL, NamespaceId, SubspaceId>
}
impl fmt::Debug for PrivateAreaContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl PrivateAreaContext {
/// Returns a new [`PrivateAreaContext`] with the given `private` and `rel` attributes. Will fail if the given [`PrivateInterest`]'s path is not a prefix of `rel`'s path.
pub fn new(private: PrivateInterest, rel: Area) -> Result<Self, AreaNotAlmostIncludedError> {
let inner = PrivateAreaContextGeneric::new(private.into(), rel.into())?;
Ok(Self(inner))
}
/// Returns the [`PrivateInterest`] of this [`PrivateAreaContext`].
pub fn private(&self) -> &PrivateInterest {
self.0.private().into()
}
/// Returns the relative [`Area`] of this [`PrivateAreaContext`].
pub fn rel(&self) -> &Area {
self.0.rel().into()
}
/// Returns whether an [`Area`] _almost includes_ another area, that is if the other [`Area`] would be included by this [`Area] if it had the same [`SubspaceId`].
pub fn almost_includes_area(&self, other: &Area) -> bool {
self.0.almost_includes_area(other.into())
}
}
impl RelativeEncodable<PrivateAreaContext> for Area {
async fn relative_encode<C>(
&self,
rel: &PrivateAreaContext,
consumer: &mut C,
) -> Result<(), C::Error>
where
C: ufotofu::BulkConsumer<Item = u8> + ?Sized,
{
self.0
.relative_encode(
<&PrivateAreaContextGeneric<MCL, MCC, MPL, NamespaceId, SubspaceId>>::from(rel),
consumer,
)
.await
}
/// Returns `false` when `self` is not [almost included by](https://willowprotocol.org/specs/encodings/index.html#almost_include) the relative [`PrivateAreaContext`].
fn can_be_encoded_relative_to(&self, rel: &PrivateAreaContext) -> bool {
self.0
.can_be_encoded_relative_to(<&PrivateAreaContextGeneric<
MCL,
MCC,
MPL,
NamespaceId,
SubspaceId,
>>::from(rel))
}
}
impl RelativeDecodable<PrivateAreaContext> for Area {
type ErrorReason = Blame;
async fn relative_decode<P>(
rel: &PrivateAreaContext,
producer: &mut P,
) -> Result<Self, ufotofu::codec::DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: ufotofu::BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
let inner =
willow_data_model::groupings::Area::<MCL, MCC, MPL, SubspaceId>::relative_decode(
<&PrivateAreaContextGeneric<MCL, MCC, MPL, NamespaceId, SubspaceId>>::from(rel),
producer,
)
.await?;
Ok(Self(inner))
}
}