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
use samod_core::{DocumentId, PeerId};
/// Whether to announce a document to a peer
///
/// To configure announcement behavior implement this trait and pass the
/// implementation to
/// [`RepoBuilder::with_announce_policy`](crate::RepoBuilder::with_announce_policy).
/// Note that the trait is implemented for `Fn(DocumentId, PeerId) -> bool`, so
/// a closure can be passed directly in many cases.
pub trait AnnouncePolicy: Clone + Send + 'static {
/// Whether we should announce the given document to the given peer ID. This
/// is used like so:
///
/// * When we connect to a new peer we check this for each
/// [`DocHandle`](crate::DocHandle) we are synchronizing
/// * When we create a new [`DocHandle`](crate::DocHandle) we check this for
/// each connected peer
/// * When we request a new document using [`Repo::find`](crate::Repo::find)
/// we check this for each connected peer before sending a request (this
/// prevents leaking document IDs)
///
/// Note that the peer IDs are not authenticated by the network protocol
/// `samod` implements, so if you are relying on this method for
/// authorization you must make sure that the network layer you provide is
/// doing authentication in it's own fashion somehow.
fn should_announce(
&self,
doc_id: DocumentId,
peer_id: PeerId,
) -> impl Future<Output = bool> + Send + 'static;
}
/// A version of [`AnnouncePolicy`] that can be used with runtimes that don't
/// require `Send` or `'static` bounds. See the [module level documentation on
/// runtimes](./index.html#runtimes) for more details.
pub trait LocalAnnouncePolicy: Clone + 'static {
fn should_announce(&self, doc_id: DocumentId, peer_id: PeerId) -> impl Future<Output = bool>;
}
impl<A: AnnouncePolicy> LocalAnnouncePolicy for A {
fn should_announce(&self, doc_id: DocumentId, peer_id: PeerId) -> impl Future<Output = bool> {
AnnouncePolicy::should_announce(self, doc_id, peer_id)
}
}
impl<F> AnnouncePolicy for F
where
F: Fn(DocumentId, PeerId) -> bool + Clone + Send + 'static,
{
fn should_announce(
&self,
doc_id: DocumentId,
peer_id: PeerId,
) -> impl Future<Output = bool> + Send + 'static {
let result = self(doc_id, peer_id);
async move { result }
}
}
/// Always announce every documents to every peer
#[derive(Clone)]
pub struct AlwaysAnnounce;
impl AnnouncePolicy for AlwaysAnnounce {
#[allow(clippy::manual_async_fn)]
fn should_announce(
&self,
_doc_id: DocumentId,
_peer_id: PeerId,
) -> impl Future<Output = bool> + Send + 'static {
async { true }
}
}
/// Always announce every documents to every peer
#[derive(Clone)]
pub struct NeverAnnounce;
impl AnnouncePolicy for NeverAnnounce {
#[allow(clippy::manual_async_fn)]
fn should_announce(
&self,
_doc_id: DocumentId,
_peer_id: PeerId,
) -> impl Future<Output = bool> + Send + 'static {
async { false }
}
}