1use crate::{
4 lines::common::{Addrtype, Nettype},
5 Error,
6};
7use std::{convert::TryFrom, net::IpAddr};
8
9pub use crate::tokenizers::origin::Tokenizer;
12
13#[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}