1use clock::ReplicaId;
2
3pub struct Network<T: Clone, R: rand::Rng> {
4 inboxes: std::collections::BTreeMap<ReplicaId, Vec<Envelope<T>>>,
5 all_messages: Vec<T>,
6 rng: R,
7}
8
9#[derive(Clone)]
10struct Envelope<T: Clone> {
11 message: T,
12}
13
14impl<T: Clone, R: rand::Rng> Network<T, R> {
15 pub fn new(rng: R) -> Self {
16 Network {
17 inboxes: Default::default(),
18 all_messages: Vec::new(),
19 rng,
20 }
21 }
22
23 pub fn add_peer(&mut self, id: ReplicaId) {
24 self.inboxes.insert(id, Vec::new());
25 }
26
27 pub fn replicate(&mut self, old_replica_id: ReplicaId, new_replica_id: ReplicaId) {
28 self.inboxes
29 .insert(new_replica_id, self.inboxes[&old_replica_id].clone());
30 }
31
32 pub fn is_idle(&self) -> bool {
33 self.inboxes.values().all(|i| i.is_empty())
34 }
35
36 pub fn broadcast(&mut self, sender: ReplicaId, messages: Vec<T>) {
37 for (replica, inbox) in self.inboxes.iter_mut() {
38 if *replica != sender {
39 for message in &messages {
40 // Insert one or more duplicates of this message, potentially *before* the previous
41 // message sent by this peer to simulate out-of-order delivery.
42 for _ in 0..self.rng.gen_range(1..4) {
43 let insertion_index = self.rng.gen_range(0..inbox.len() + 1);
44 inbox.insert(
45 insertion_index,
46 Envelope {
47 message: message.clone(),
48 },
49 );
50 }
51 }
52 }
53 }
54 self.all_messages.extend(messages);
55 }
56
57 pub fn has_unreceived(&self, receiver: ReplicaId) -> bool {
58 !self.inboxes[&receiver].is_empty()
59 }
60
61 pub fn receive(&mut self, receiver: ReplicaId) -> Vec<T> {
62 let inbox = self.inboxes.get_mut(&receiver).unwrap();
63 let count = self.rng.gen_range(0..inbox.len() + 1);
64 inbox
65 .drain(0..count)
66 .map(|envelope| envelope.message)
67 .collect()
68 }
69}