snops_common/state/
port_config.rs

1use crate::format::{DataFormat, DataFormatReader};
2
3#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, clap::Parser)]
4pub struct PortConfig {
5    /// Specify the IP address and port for the node server
6    #[clap(long = "node", default_value_t = 4130)]
7    pub node: u16,
8
9    /// Specify the IP address and port for the BFT
10    #[clap(long = "bft", default_value_t = 5000)]
11    pub bft: u16,
12
13    /// Specify the IP address and port for the REST server
14    #[clap(long = "rest", default_value_t = 3030)]
15    pub rest: u16,
16
17    /// Specify the port for the metrics
18    #[clap(long = "metrics", default_value_t = 9000)]
19    pub metrics: u16,
20}
21
22impl std::fmt::Display for PortConfig {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        write!(
25            f,
26            "bft: {}, node: {}, rest: {}",
27            self.bft, self.node, self.rest
28        )
29    }
30}
31
32impl DataFormat for PortConfig {
33    type Header = u8;
34    const LATEST_HEADER: Self::Header = 1;
35
36    fn write_data<W: std::io::prelude::Write>(
37        &self,
38        writer: &mut W,
39    ) -> Result<usize, crate::format::DataWriteError> {
40        let mut written = 0;
41        written += self.node.write_data(writer)?;
42        written += self.bft.write_data(writer)?;
43        written += self.rest.write_data(writer)?;
44        written += self.metrics.write_data(writer)?;
45        Ok(written)
46    }
47
48    fn read_data<R: std::io::prelude::Read>(
49        reader: &mut R,
50        header: &Self::Header,
51    ) -> Result<Self, crate::format::DataReadError> {
52        if *header != Self::LATEST_HEADER {
53            return Err(crate::format::DataReadError::unsupported(
54                "PortConfig",
55                Self::LATEST_HEADER,
56                *header,
57            ));
58        }
59
60        Ok(PortConfig {
61            node: reader.read_data(&())?,
62            bft: reader.read_data(&())?,
63            rest: reader.read_data(&())?,
64            metrics: reader.read_data(&())?,
65        })
66    }
67}
68
69#[cfg(test)]
70mod test {
71    use crate::format::DataFormat;
72    use crate::state::PortConfig;
73
74    macro_rules! case {
75        ($name:ident, $ty:ty, $a:expr, $b:expr) => {
76            #[test]
77            fn $name() -> Result<(), Box<dyn std::error::Error>> {
78                let mut data = Vec::new();
79                $a.write_data(&mut data).unwrap();
80                assert_eq!(data, $b);
81
82                let mut reader = &data[..];
83                let read_value =
84                    <$ty>::read_data(&mut reader, &<$ty as DataFormat>::LATEST_HEADER).unwrap();
85
86                // write the data again because not every type implements PartialEq
87                let mut data2 = Vec::new();
88                read_value.write_data(&mut data2).unwrap();
89                assert_eq!(data, data2);
90                Ok(())
91            }
92        };
93    }
94
95    case!(
96        port_config,
97        PortConfig,
98        PortConfig {
99            node: 0,
100            bft: 1,
101            rest: 2,
102            metrics: 3,
103        },
104        [0, 0, 1, 0, 2, 0, 3, 0]
105    );
106}