1use std::{
2 fmt::{self, Display, Formatter},
3 str::FromStr,
4};
5
6use str_reader::StringReader;
7
8use crate::{AddressType, NetworkType, ParseError};
9
10#[derive(Clone)]
12pub struct Origin {
13 username: String,
14 session_id: u64,
15 session_version: u64,
16 network_type: NetworkType,
17 address_type: AddressType,
18 unicast_address: String,
19}
20
21impl Origin {
22 #[inline]
24 pub fn new<U, A>(
25 username: U,
26 session_id: u64,
27 session_version: u64,
28 network_type: NetworkType,
29 address_type: AddressType,
30 unicast_address: A,
31 ) -> Self
32 where
33 U: ToString,
34 A: ToString,
35 {
36 Self {
37 username: username.to_string(),
38 session_id,
39 session_version,
40 network_type,
41 address_type,
42 unicast_address: unicast_address.to_string(),
43 }
44 }
45
46 #[inline]
48 pub fn username(&self) -> &str {
49 &self.username
50 }
51
52 #[inline]
54 pub fn session_id(&self) -> u64 {
55 self.session_id
56 }
57
58 #[inline]
60 pub fn session_version(&self) -> u64 {
61 self.session_version
62 }
63
64 #[inline]
66 pub fn network_type(&self) -> &NetworkType {
67 &self.network_type
68 }
69
70 #[inline]
72 pub fn address_type(&self) -> &AddressType {
73 &self.address_type
74 }
75
76 #[inline]
78 pub fn unicast_address(&self) -> &str {
79 &self.unicast_address
80 }
81}
82
83impl Default for Origin {
84 #[inline]
85 fn default() -> Self {
86 Self {
87 username: String::from("-"),
88 session_id: 0,
89 session_version: 0,
90 network_type: NetworkType::Internet,
91 address_type: AddressType::IPv4,
92 unicast_address: String::from("0.0.0.0"),
93 }
94 }
95}
96
97impl Display for Origin {
98 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
99 write!(
100 f,
101 "{} {} {} {} {} {}",
102 self.username,
103 self.session_id,
104 self.session_version,
105 self.network_type,
106 self.address_type,
107 self.unicast_address
108 )
109 }
110}
111
112impl FromStr for Origin {
113 type Err = ParseError;
114
115 fn from_str(s: &str) -> Result<Self, Self::Err> {
116 let mut reader = StringReader::new(s);
117
118 let username = reader.read_word().to_string();
119 let session_id = reader.read_u64()?;
120 let session_version = reader.read_u64()?;
121 let network_type = reader.parse_word()?;
122 let address_type = reader.parse_word()?;
123 let unicast_address = reader.read_word().to_string();
124
125 reader.skip_whitespace();
126
127 if unicast_address.is_empty() || !reader.is_empty() {
128 return Err(ParseError::plain());
129 }
130
131 let res = Self {
132 username,
133 session_id,
134 session_version,
135 network_type,
136 address_type,
137 unicast_address,
138 };
139
140 Ok(res)
141 }
142}