sdp_rs/lines/
origin.rs

1//! Types related to the origin line (`o=`).
2
3use crate::{
4    lines::common::{Addrtype, Nettype},
5    Error,
6};
7use std::{convert::TryFrom, net::IpAddr};
8
9/// The origin line (`o=`) tokenizer. This is low level stuff and you shouldn't interact directly
10/// with it, unless you know what you are doing.
11pub use crate::tokenizers::origin::Tokenizer;
12
13/// The origin line (`o=`) of SDP.
14#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Clone)]
15pub struct Origin {
16    pub username: String,
17    pub sess_id: String,
18    pub sess_version: String,
19    pub nettype: Nettype,
20    pub addrtype: Addrtype,
21    pub unicast_address: IpAddr,
22}
23
24impl<'a> TryFrom<Tokenizer<'a>> for Origin {
25    type Error = Error;
26
27    fn try_from(tokenizer: Tokenizer<'a>) -> Result<Self, Self::Error> {
28        Ok(Self {
29            username: tokenizer.username.into(),
30            sess_id: tokenizer.sess_id.into(),
31            sess_version: tokenizer.sess_version.into(),
32            nettype: tokenizer.nettype.into(),
33            addrtype: tokenizer.addrtype.into(),
34            unicast_address: tokenizer.unicast_address.parse().map_err(|e| {
35                Self::Error::parser_with_error("origin ip address", tokenizer.unicast_address, e)
36            })?,
37        })
38    }
39}
40
41impl std::fmt::Display for Origin {
42    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43        write!(
44            f,
45            "o={} {} {} {} {} {}",
46            self.username,
47            self.sess_id,
48            self.sess_version,
49            self.nettype,
50            self.addrtype,
51            self.unicast_address
52        )
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use std::net::Ipv4Addr;
60
61    #[test]
62    fn from_tokenizer1() {
63        let tokenizer = Tokenizer {
64            username: "jdoe",
65            sess_id: "3724394400",
66            sess_version: "3724394405",
67            nettype: "IN",
68            addrtype: "IP4",
69            unicast_address: "198.51.100.1",
70        };
71
72        assert_eq!(
73            Origin::try_from(tokenizer),
74            Ok(Origin {
75                username: "jdoe".into(),
76                sess_id: "3724394400".into(),
77                sess_version: "3724394405".into(),
78                nettype: Nettype::In,
79                addrtype: Addrtype::Ip4,
80                unicast_address: IpAddr::V4(Ipv4Addr::new(198, 51, 100, 1)),
81            })
82        );
83    }
84
85    #[test]
86    fn from_tokenizer2() {
87        let tokenizer = Tokenizer {
88            username: "jdoe",
89            sess_id: "3724394400",
90            sess_version: "3724394405",
91            nettype: "IN",
92            addrtype: "IP4",
93            unicast_address: "noip",
94        };
95
96        assert!(Origin::try_from(tokenizer).is_err());
97    }
98
99    #[test]
100    fn display1() {
101        let origin = Origin {
102            username: "jdoe".into(),
103            sess_id: "3724394400".into(),
104            sess_version: "3724394405".into(),
105            nettype: Nettype::In,
106            addrtype: Addrtype::Ip4,
107            unicast_address: IpAddr::V4(Ipv4Addr::new(198, 51, 100, 1)),
108        };
109
110        assert_eq!(
111            origin.to_string(),
112            "o=jdoe 3724394400 3724394405 IN IP4 198.51.100.1"
113        );
114    }
115}