ezk_sdp_types/
connection.rs1use crate::{slash_num, TaggedAddress};
2use bytes::Bytes;
3use internal::IResult;
4use nom::combinator::opt;
5use nom::sequence::pair;
6use std::fmt;
7
8#[derive(Debug, Clone)]
12pub struct Connection {
13 pub address: TaggedAddress,
15
16 pub ttl: Option<u32>,
18
19 pub num: Option<u32>,
21}
22
23impl Connection {
24 pub fn parse<'i>(src: &Bytes, i: &'i str) -> IResult<&'i str, Self> {
25 let (i, address) = TaggedAddress::parse(src)(i)?;
26
27 match &address {
28 TaggedAddress::IP4(_) | TaggedAddress::IP4FQDN(_) => {
29 let (i, ttl) = opt(pair(slash_num, opt(slash_num)))(i)?;
30
31 let (ttl, num) = match ttl {
32 None => (None, None),
33 Some((ttl, num)) => (Some(ttl), num),
34 };
35
36 Ok((i, Connection { address, ttl, num }))
37 }
38 TaggedAddress::IP6(_) | TaggedAddress::IP6FQDN(_) => {
39 let (i, num) = opt(slash_num)(i)?;
40
41 Ok((
42 i,
43 Connection {
44 address,
45 ttl: None,
46 num,
47 },
48 ))
49 }
50 }
51 }
52}
53
54impl fmt::Display for Connection {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 write!(f, "{}", self.address)?;
57
58 match self.address {
59 TaggedAddress::IP4(_) | TaggedAddress::IP4FQDN(_) => {
60 if let Some(ttl) = self.ttl {
61 write!(f, "/{}", ttl)?;
62
63 if let Some(num) = self.num {
64 write!(f, "/{}", num)?;
65 }
66 }
67 }
68 TaggedAddress::IP6(_) | TaggedAddress::IP6FQDN(_) => {
69 if let Some(num) = self.num {
70 write!(f, "/{}", num)?;
71 }
72 }
73 }
74
75 Ok(())
76 }
77}
78
79#[cfg(test)]
80mod test {
81 use super::*;
82 use bytesstr::BytesStr;
83 use std::net::Ipv4Addr;
84
85 #[test]
86 fn connection() {
87 let input = BytesStr::from_static("IN IP4 192.168.123.222");
88
89 let (rem, connection) = Connection::parse(input.as_ref(), &input).unwrap();
90
91 assert!(rem.is_empty());
92
93 assert!(
94 matches!(connection.address, TaggedAddress::IP4(ip) if ip == Ipv4Addr::new(192, 168, 123, 222))
95 )
96 }
97
98 #[test]
99 fn connection_ttl() {
100 let input = BytesStr::from_static("IN IP4 192.168.123.222/127");
101
102 let (rem, connection) = Connection::parse(input.as_ref(), &input).unwrap();
103
104 assert!(rem.is_empty());
105
106 assert!(
107 matches!(connection.address, TaggedAddress::IP4(ip) if ip == Ipv4Addr::new(192, 168, 123, 222))
108 );
109 assert_eq!(connection.ttl, Some(127));
110 assert_eq!(connection.num, None);
111 }
112
113 #[test]
114 fn connection_ttl_num() {
115 let input = BytesStr::from_static("IN IP4 192.168.123.222/127/3");
116
117 let (rem, connection) = Connection::parse(input.as_ref(), &input).unwrap();
118
119 assert!(rem.is_empty());
120
121 assert!(
122 matches!(connection.address, TaggedAddress::IP4(ip) if ip == Ipv4Addr::new(192, 168, 123, 222))
123 );
124 assert_eq!(connection.ttl, Some(127));
125 assert_eq!(connection.num, Some(3));
126 }
127
128 #[test]
129 fn connection_print() {
130 let connection = Connection {
131 address: TaggedAddress::IP4(Ipv4Addr::new(192, 168, 123, 222)),
132 ttl: None,
133 num: None,
134 };
135
136 assert_eq!(connection.to_string(), "IN IP4 192.168.123.222");
137 }
138
139 #[test]
140 fn connection_print_ttl() {
141 let connection = Connection {
142 address: TaggedAddress::IP4(Ipv4Addr::new(192, 168, 0, 1)),
143 ttl: Some(127),
144 num: None,
145 };
146
147 assert_eq!(connection.to_string(), "IN IP4 192.168.0.1/127");
148 }
149
150 #[test]
151 fn connection_print_ttl_num() {
152 let connection = Connection {
153 address: TaggedAddress::IP4(Ipv4Addr::new(192, 168, 0, 1)),
154 ttl: Some(127),
155 num: Some(3),
156 };
157
158 assert_eq!(connection.to_string(), "IN IP4 192.168.0.1/127/3");
159 }
160
161 #[test]
162 fn connection_print_num_without_ttl() {
163 let connection = Connection {
164 address: TaggedAddress::IP4(Ipv4Addr::new(192, 168, 0, 1)),
165 ttl: None,
166 num: Some(3),
167 };
168
169 assert_eq!(connection.to_string(), "IN IP4 192.168.0.1");
170 }
171}