rip_rs/
v2.rs

1use crate::metric::Metric;
2use crate::route_tag::RouteTag;
3use crate::serializer::{Serializable, SerializeError};
4use crate::{address_family, ipv4, metric, parser::PacketParsable, parser::ParseError, route_tag};
5use std::net::Ipv4Addr;
6
7#[derive(PartialEq, Debug)]
8pub struct Entry {
9    address_family_identifier: address_family::Identifier,
10    route_tag: RouteTag,
11    ip_address: Ipv4Addr,
12    subnet_mask: Ipv4Addr,
13    next_hop: Ipv4Addr,
14    metric: Metric,
15}
16
17impl Entry {
18    pub fn new(
19        address_family_identifier: address_family::Identifier,
20        route_tag: RouteTag,
21        ip_address: Ipv4Addr,
22        subnet_mask: Ipv4Addr,
23        next_hop: Ipv4Addr,
24        metric: Metric,
25    ) -> Self {
26        Entry {
27            address_family_identifier,
28            route_tag,
29            ip_address,
30            subnet_mask,
31            next_hop,
32            metric,
33        }
34    }
35
36    pub fn get_address_family_identifier(&self) -> address_family::Identifier {
37        self.address_family_identifier
38    }
39
40    pub fn get_route_tag(&self) -> RouteTag {
41        self.route_tag
42    }
43
44    pub fn get_ip_address(&self) -> Ipv4Addr {
45        self.ip_address
46    }
47
48    pub fn get_subnet_mask(&self) -> Ipv4Addr {
49        self.subnet_mask
50    }
51
52    pub fn get_next_hop(&self) -> Ipv4Addr {
53        self.next_hop
54    }
55
56    pub fn get_metric(&self) -> Metric {
57        self.metric
58    }
59}
60
61impl Serializable for Entry {
62    fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
63        Ok([
64            self.get_address_family_identifier().to_bytes()?,
65            route_tag::to_bytes(self.get_route_tag())?,
66            ipv4::to_bytes(self.get_ip_address())?,
67            ipv4::to_bytes(self.get_subnet_mask())?,
68            ipv4::to_bytes(self.get_next_hop())?,
69            metric::to_bytes(self.get_metric())?,
70        ]
71        .concat())
72    }
73}
74
75pub struct EntriesParser {}
76
77impl PacketParsable<Entry> for EntriesParser {
78    fn parse_entry<'a>(
79        &'a self,
80        cursor: usize,
81        bytes: &'a [u8],
82    ) -> Result<(Entry, usize), ParseError> {
83        let (address_family_identifier, cursor) = address_family::Identifier::parse(cursor, bytes)?;
84        let (route_tag, cursor) = route_tag::parse(cursor, bytes)?;
85        let (ip_address, cursor) = ipv4::parse(cursor, bytes)?;
86        let (subnet_mask, cursor) = ipv4::parse(cursor, bytes)?;
87        let (next_hop, cursor) = ipv4::parse(cursor, bytes)?;
88        let (metric, cursor) = metric::parse(cursor, bytes)?;
89
90        Ok((
91            Entry::new(
92                address_family_identifier,
93                route_tag,
94                ip_address,
95                subnet_mask,
96                next_hop,
97                metric,
98            ),
99            cursor,
100        ))
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use crate::v2::{EntriesParser, Entry};
107    use crate::{address_family, parser};
108    use std::net::Ipv4Addr;
109
110    #[test]
111    fn test_parse_packet_for_single_entry() {
112        let parser = EntriesParser {};
113        let result = parser::parse_entries(
114            &parser,
115            4,
116            vec![
117                2, 2, 0, 0, //
118                0, 2, 1, 2, //
119                192, 0, 2, 100, //
120                255, 255, 255, 0, //
121                192, 0, 2, 111, //
122                4, 3, 2, 1, //
123            ]
124            .as_slice(),
125        );
126
127        assert_eq!(result.is_ok(), true);
128
129        let entries = result.unwrap();
130        assert_eq!(
131            entries,
132            vec![Entry {
133                address_family_identifier: address_family::Identifier::IP,
134                route_tag: 258,
135                ip_address: Ipv4Addr::new(192, 0, 2, 100),
136                subnet_mask: Ipv4Addr::new(255, 255, 255, 0),
137                next_hop: Ipv4Addr::new(192, 0, 2, 111),
138                metric: 67305985,
139            }]
140        );
141    }
142
143    #[test]
144    fn test_parse_packet_for_multiple_entry() {
145        let parser = EntriesParser {};
146        let result = parser::parse_entries(
147            &parser,
148            4,
149            vec![
150                2, 2, 0, 0, //
151                0, 2, 1, 2, //
152                192, 0, 2, 100, //
153                255, 255, 255, 0, //
154                192, 0, 2, 200, //
155                4, 3, 2, 1, //
156                0, 2, 0, 1, //
157                192, 0, 2, 101, //
158                255, 255, 255, 0, //
159                192, 0, 2, 201, //
160                0, 0, 0, 1, //
161                0, 2, 0, 2, //
162                192, 0, 2, 102, //
163                255, 255, 255, 0, //
164                192, 0, 2, 202, //
165                0, 0, 0, 2, //
166            ]
167            .as_slice(),
168        );
169
170        assert_eq!(result.is_ok(), true);
171
172        let entries = result.unwrap();
173        assert_eq!(
174            entries,
175            vec![
176                Entry {
177                    address_family_identifier: address_family::Identifier::IP,
178                    route_tag: 258,
179                    ip_address: Ipv4Addr::new(192, 0, 2, 100),
180                    subnet_mask: Ipv4Addr::new(255, 255, 255, 0),
181                    next_hop: Ipv4Addr::new(192, 0, 2, 200),
182                    metric: 67305985,
183                },
184                Entry {
185                    address_family_identifier: address_family::Identifier::IP,
186                    route_tag: 1,
187                    ip_address: Ipv4Addr::new(192, 0, 2, 101),
188                    subnet_mask: Ipv4Addr::new(255, 255, 255, 0),
189                    next_hop: Ipv4Addr::new(192, 0, 2, 201),
190                    metric: 1,
191                },
192                Entry {
193                    address_family_identifier: address_family::Identifier::IP,
194                    route_tag: 2,
195                    ip_address: Ipv4Addr::new(192, 0, 2, 102),
196                    subnet_mask: Ipv4Addr::new(255, 255, 255, 0),
197                    next_hop: Ipv4Addr::new(192, 0, 2, 202),
198                    metric: 2,
199                },
200            ]
201        );
202    }
203}