cold_io/
request.rs

1// Copyright 2021 Vladislav Melnik
2// SPDX-License-Identifier: MIT
3
4use std::{net::SocketAddr, mem, ops::AddAssign, fmt};
5use smallvec::SmallVec;
6
7/// The proposer will perform requests sequentially.
8/// First it setup source, then blacklists and then disconnect.
9#[derive(Default, Debug)]
10pub struct Request {
11    source: Option<ConnectionSource>,
12    blacklist: SmallVec<[SocketAddr; 4]>,
13    connect: SmallVec<[SocketAddr; 8]>,
14}
15
16impl Request {
17    pub fn set_source(self, source: ConnectionSource) -> Self {
18        let mut s = self;
19        s.source = Some(source);
20        s
21    }
22
23    pub fn add_to_blacklist<A>(self, addr: A) -> Self
24    where
25        A: Into<SocketAddr>,
26    {
27        let mut s = self;
28        s.blacklist.push(addr.into());
29        s
30    }
31
32    pub fn add_batch_to_blacklist<I>(self, batch: I) -> Self
33    where
34        I: IntoIterator<Item = SocketAddr>,
35    {
36        let mut s = self;
37        s.blacklist.extend(batch);
38        s
39    }
40
41    pub fn add_connect<A>(self, addr: A) -> Self
42    where
43        A: Into<SocketAddr>,
44    {
45        let mut s = self;
46        s.connect.push(addr.into());
47        s
48    }
49
50    pub fn add_batch_connect<I>(self, batch: I) -> Self
51    where
52        I: IntoIterator<Item = SocketAddr>,
53    {
54        let mut s = self;
55        s.connect.extend(batch);
56        s
57    }
58
59    pub fn is_empty(&self) -> bool {
60        self.source.is_none() && self.blacklist.is_empty() && self.connect.is_empty()
61    }
62
63    pub fn take_new_source(&mut self) -> Option<ConnectionSource> {
64        self.source.take()
65    }
66
67    pub fn take_blacklist(&mut self) -> impl Iterator<Item = SocketAddr> {
68        mem::take(&mut self.blacklist).into_iter()
69    }
70
71    pub fn take_connects(&mut self) -> impl Iterator<Item = SocketAddr> {
72        mem::take(&mut self.connect).into_iter()
73    }
74}
75
76impl AddAssign<Request> for Request {
77    fn add_assign(&mut self, rhs: Request) {
78        let Request {
79            source,
80            mut blacklist,
81            mut connect,
82        } = rhs;
83        #[allow(clippy::suspicious_op_assign_impl)]
84        if self.source.is_none() && source.is_some() {
85            self.source = source;
86        }
87        self.blacklist.append(&mut blacklist);
88        self.connect.append(&mut connect);
89    }
90}
91
92/// Choose how the proposer will listen incoming connections
93#[derive(Debug, Clone, Copy)]
94pub enum ConnectionSource {
95    /// No incoming connections allowed
96    None,
97    /// Listen at port
98    Port(u16),
99}
100
101impl fmt::Display for ConnectionSource {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        match self {
104            ConnectionSource::None => write!(f, "none"),
105            ConnectionSource::Port(port) => write!(f, "port({})", port),
106        }
107    }
108}