msf_sdp/
connection.rs

1//! Connection information.
2
3use std::{
4    fmt::{self, Display, Formatter},
5    net::{IpAddr, Ipv4Addr, Ipv6Addr},
6    str::FromStr,
7};
8
9use str_reader::StringReader;
10
11use crate::{NetworkType, ParseError};
12
13/// Connection information.
14#[derive(Clone)]
15pub struct ConnectionInfo {
16    network_type: NetworkType,
17    address: ConnectionAddress,
18}
19
20impl ConnectionInfo {
21    /// Create a new connection info.
22    #[inline]
23    pub fn new<T>(network_type: NetworkType, address: T) -> Self
24    where
25        T: Into<ConnectionAddress>,
26    {
27        let address = address.into();
28
29        Self {
30            network_type,
31            address,
32        }
33    }
34
35    /// Get the network type.
36    #[inline]
37    pub fn network_type(&self) -> &NetworkType {
38        &self.network_type
39    }
40
41    /// Get the connection address.
42    #[inline]
43    pub fn address(&self) -> &ConnectionAddress {
44        &self.address
45    }
46}
47
48impl Display for ConnectionInfo {
49    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
50        write!(f, "{} {}", self.network_type, self.address)
51    }
52}
53
54impl FromStr for ConnectionInfo {
55    type Err = ParseError;
56
57    fn from_str(s: &str) -> Result<Self, Self::Err> {
58        let mut reader = StringReader::new(s);
59
60        let network_type = reader.parse_word()?;
61        let address = reader.as_str().parse()?;
62
63        let res = Self {
64            network_type,
65            address,
66        };
67
68        Ok(res)
69    }
70}
71
72/// Connection address.
73#[derive(Clone)]
74pub enum ConnectionAddress {
75    IPv4(IPv4Address),
76    IPv6(IPv6Address),
77    Other(OtherAddress),
78}
79
80impl ConnectionAddress {
81    /// Create unicast connection address from a given IP address.
82    #[inline]
83    pub fn unicast<A>(addr: A) -> Self
84    where
85        A: Into<IpAddr>,
86    {
87        match addr.into() {
88            IpAddr::V4(addr) => Self::IPv4(IPv4Address::unicast(addr)),
89            IpAddr::V6(addr) => Self::IPv6(IPv6Address::unicast(addr)),
90        }
91    }
92}
93
94impl Display for ConnectionAddress {
95    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
96        match self {
97            Self::IPv4(addr) => write!(f, "IP4 {addr}"),
98            Self::IPv6(addr) => write!(f, "IP6 {addr}"),
99            Self::Other(addr) => write!(f, "{} {}", addr.address_type, addr),
100        }
101    }
102}
103
104impl FromStr for ConnectionAddress {
105    type Err = ParseError;
106
107    fn from_str(s: &str) -> Result<Self, Self::Err> {
108        let mut reader = StringReader::new(s);
109
110        let address_type = reader.read_word();
111        let address = reader.as_str();
112
113        let res = match address_type {
114            "IP4" => Self::IPv4(address.parse()?),
115            "IP6" => Self::IPv6(address.parse()?),
116            _ => Self::Other(OtherAddress::new(address_type, address.trim())),
117        };
118
119        Ok(res)
120    }
121}
122
123impl From<IPv4Address> for ConnectionAddress {
124    #[inline]
125    fn from(addr: IPv4Address) -> Self {
126        Self::IPv4(addr)
127    }
128}
129
130impl From<IPv6Address> for ConnectionAddress {
131    #[inline]
132    fn from(addr: IPv6Address) -> Self {
133        Self::IPv6(addr)
134    }
135}
136
137impl From<OtherAddress> for ConnectionAddress {
138    #[inline]
139    fn from(addr: OtherAddress) -> Self {
140        Self::Other(addr)
141    }
142}
143
144/// IPv4 connection address.
145#[derive(Copy, Clone)]
146pub struct IPv4Address {
147    address: Ipv4Addr,
148    ttl: Option<u8>,
149    count: Option<u32>,
150}
151
152impl IPv4Address {
153    /// Create a single unicast IPv4 connection address.
154    #[inline]
155    pub const fn unicast(address: Ipv4Addr) -> Self {
156        Self {
157            address,
158            ttl: None,
159            count: None,
160        }
161    }
162
163    /// Create multicast IPv4 connection address(es).
164    #[inline]
165    pub const fn multicast(address: Ipv4Addr, ttl: u8, count: Option<u32>) -> Self {
166        Self {
167            address,
168            ttl: Some(ttl),
169            count,
170        }
171    }
172
173    /// Get the IP address.
174    #[inline]
175    pub fn address(&self) -> Ipv4Addr {
176        self.address
177    }
178
179    /// Get multicast TTL value.
180    #[inline]
181    pub fn ttl(&self) -> Option<u8> {
182        self.ttl
183    }
184
185    /// Get number of addresses.
186    #[inline]
187    pub fn count(&self) -> Option<u32> {
188        self.count
189    }
190}
191
192impl Display for IPv4Address {
193    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
194        write!(f, "{}", self.address)?;
195
196        if let Some(ttl) = self.ttl {
197            write!(f, "/{ttl}")?;
198
199            if let Some(count) = self.count {
200                write!(f, "/{count}")?;
201            }
202        }
203
204        Ok(())
205    }
206}
207
208impl FromStr for IPv4Address {
209    type Err = ParseError;
210
211    fn from_str(s: &str) -> Result<Self, Self::Err> {
212        let mut reader = StringReader::new(s);
213
214        let address = reader.parse_word()?;
215
216        reader.skip_whitespace();
217
218        let ttl = if reader.is_empty() {
219            None
220        } else {
221            reader.match_char('/')?;
222
223            Some(reader.read_u8()?)
224        };
225
226        reader.skip_whitespace();
227
228        let count = if reader.is_empty() {
229            None
230        } else {
231            reader.match_char('/')?;
232
233            Some(reader.read_u32()?)
234        };
235
236        reader.skip_whitespace();
237
238        if !reader.is_empty() {
239            return Err(ParseError::plain());
240        }
241
242        let res = Self {
243            address,
244            ttl,
245            count,
246        };
247
248        Ok(res)
249    }
250}
251
252/// IPv6 connection address.
253#[derive(Copy, Clone)]
254pub struct IPv6Address {
255    address: Ipv6Addr,
256    count: Option<u32>,
257}
258
259impl IPv6Address {
260    /// Create a single unicast IPv6 connection address.
261    #[inline]
262    pub const fn unicast(address: Ipv6Addr) -> Self {
263        Self {
264            address,
265            count: None,
266        }
267    }
268
269    /// Create multicast IPv6 connection address(es).
270    #[inline]
271    pub const fn multicast(address: Ipv6Addr, count: Option<u32>) -> Self {
272        Self { address, count }
273    }
274
275    /// Get the IPv6 address.
276    #[inline]
277    pub fn address(&self) -> Ipv6Addr {
278        self.address
279    }
280
281    /// Get number of addresses.
282    #[inline]
283    pub fn count(&self) -> Option<u32> {
284        self.count
285    }
286}
287
288impl Display for IPv6Address {
289    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
290        write!(f, "{}", self.address)?;
291
292        if let Some(count) = self.count {
293            write!(f, "/{count}")?;
294        }
295
296        Ok(())
297    }
298}
299
300impl FromStr for IPv6Address {
301    type Err = ParseError;
302
303    fn from_str(s: &str) -> Result<Self, Self::Err> {
304        let mut reader = StringReader::new(s);
305
306        let address = reader.parse_word()?;
307
308        reader.skip_whitespace();
309
310        let count = if reader.is_empty() {
311            None
312        } else {
313            reader.match_char('/')?;
314
315            Some(reader.read_u32()?)
316        };
317
318        reader.skip_whitespace();
319
320        if !reader.is_empty() {
321            return Err(ParseError::plain());
322        }
323
324        let res = Self { address, count };
325
326        Ok(res)
327    }
328}
329
330/// Other connection address.
331#[derive(Clone)]
332pub struct OtherAddress {
333    address_type: String,
334    address: String,
335}
336
337impl OtherAddress {
338    /// Create a new connection address that is not IPv4 or IPv6.
339    #[inline]
340    pub fn new<T, A>(address_type: T, address: A) -> Self
341    where
342        T: ToString,
343        A: ToString,
344    {
345        Self {
346            address_type: address_type.to_string(),
347            address: address.to_string(),
348        }
349    }
350
351    /// Get the type of the address.
352    #[inline]
353    pub fn address_type(&self) -> &str {
354        &self.address_type
355    }
356
357    /// Get the address.
358    #[inline]
359    pub fn address(&self) -> &str {
360        &self.address
361    }
362}
363
364impl Display for OtherAddress {
365    #[inline]
366    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
367        f.write_str(&self.address)
368    }
369}