1use crate::error::AmsAddressError;
2use crate::proto::proto_traits::{ReadFrom, WriteTo};
3use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use std::io::{self, Read, Write};
5use std::net::SocketAddr;
6use std::str::FromStr;
7
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub struct AmsAddress {
10 pub ams_net_id: AmsNetId,
11 pub port: u16,
12}
13
14impl AmsAddress {
15 pub fn new(ams_net_id: AmsNetId, port: u16) -> Self {
16 AmsAddress { ams_net_id, port }
17 }
18
19 pub fn update_from_socket_addr(
20 &mut self,
21 socket_addr: SocketAddr,
22 ) -> Result<(), AmsAddressError> {
23 let ams_address = AmsAddress::from_str(socket_addr.to_string().as_str())?;
24 self.ams_net_id = ams_address.ams_net_id;
25 self.port = ams_address.port;
26 Ok(())
27 }
28}
29
30impl WriteTo for AmsAddress {
31 fn write_to<W: Write>(&self, mut wtr: W) -> io::Result<()> {
32 self.ams_net_id.write_to(&mut wtr)?;
33 wtr.write_u16::<LittleEndian>(self.port)?;
34 Ok(())
35 }
36}
37
38impl ReadFrom for AmsAddress {
39 fn read_from<R: Read>(read: &mut R) -> io::Result<Self> {
40 Ok(AmsAddress {
41 ams_net_id: AmsNetId::read_from(read)?,
42 port: read.read_u16::<LittleEndian>()?,
43 })
44 }
45}
46
47impl FromStr for AmsAddress {
48 type Err = AmsAddressError;
49 fn from_str(socket_addr: &str) -> Result<AmsAddress, AmsAddressError> {
50 let split_socket: Vec<&str> = socket_addr.split(':').collect();
51 if split_socket.len() != 2 {
52 return Err(AmsAddressError::SplitError {
53 length: split_socket.len(),
54 });
55 }
56
57 let ams_net_id = AmsNetId::from_str(split_socket[0])?;
58
59 let port = match split_socket[1].parse::<u16>() {
60 Ok(p) => p,
61 Err(e) => return Err(AmsAddressError::ParseError { source: e }),
62 };
63 Ok(AmsAddress::new(ams_net_id, port))
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct AmsNetId {
69 net_id: [u8; 6],
70}
71
72impl WriteTo for AmsNetId {
73 fn write_to<W: Write>(&self, mut wtr: W) -> io::Result<()> {
74 wtr.write_all(&self.net_id[..])?;
75 Ok(())
76 }
77}
78
79impl ReadFrom for AmsNetId {
80 fn read_from<R: Read>(read: &mut R) -> io::Result<Self> {
81 let mut buffer: [u8; 6] = [0; 6];
82 read.read_exact(&mut buffer)?;
83 Ok(AmsNetId::from(buffer))
84 }
85}
86
87impl From<[u8; 6]> for AmsNetId {
88 fn from(net_id: [u8; 6]) -> AmsNetId {
89 AmsNetId { net_id }
90 }
91}
92
93impl FromStr for AmsNetId {
94 type Err = AmsAddressError;
95 fn from_str(net_id: &str) -> Result<AmsNetId, AmsAddressError> {
96 let mut parts: Vec<&str> = net_id.split('.').collect();
97
98 if parts.len() == 4 {
99 parts.append(&mut vec!["1", "1"]);
100 } else if parts.len() != 6 {
101 return Err(AmsAddressError::InvalidAddressLength {
102 length: parts.len(),
103 });
104 }
105
106 let mut net_id = [0; 6];
107 for (i, p) in parts.iter().enumerate() {
108 match p.parse::<u8>() {
109 Ok(v) => net_id[i] = v,
110 Err(e) => return Err(AmsAddressError::ParseError { source: e }),
111 }
112 }
113 Ok(AmsNetId { net_id })
114 }
115}
116
117impl AmsNetId {
118 #[allow(clippy::many_single_char_names)]
119 pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> AmsNetId {
120 AmsNetId {
121 net_id: [a, b, c, d, e, f],
122 }
123 }
124
125 pub fn net_id(&self) -> [u8; 6] {
126 self.net_id
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133 #[test]
134 fn ams_net_id_new_test() {
135 let ams_net_id = AmsNetId::new(192, 168, 1, 1, 1, 1);
136 assert_eq!(ams_net_id.net_id, [192, 168, 1, 1, 1, 1]);
137 }
138
139 #[test]
140 fn ams_net_id_from_test() {
141 let ams_net_id = AmsNetId::from([192, 168, 1, 1, 1, 1]);
142 assert_eq!(ams_net_id.net_id, [192, 168, 1, 1, 1, 1]);
143 }
144
145 #[test]
146 fn ams_net_id_parse_test() {
147 let ams_net_id = AmsNetId::from_str("192.168.1.1.1.1").unwrap();
148 assert_eq!(ams_net_id.net_id, [192, 168, 1, 1, 1, 1]);
149
150 let ams_parse_error = AmsNetId::from_str("192.168.1.1.1.1.1").unwrap_err();
151 assert_eq!(
152 ams_parse_error,
153 AmsAddressError::InvalidAddressLength { length: 7 }
154 );
155 }
156
157 #[test]
158 fn ams_net_id_write_to_test() {
159 let ams_net_id = AmsNetId::from([192, 168, 1, 1, 1, 1]);
160 let mut buffer: Vec<u8> = Vec::new();
161 ams_net_id.write_to(&mut buffer).unwrap();
162 assert_eq!(buffer, [192, 168, 1, 1, 1, 1]);
163 }
164
165 #[test]
166 fn ams_net_id_read_from_test() {
167 let data: Vec<u8> = vec![192, 168, 1, 1, 1, 1, 99, 6, 33]; let ams_net_id = AmsNetId::read_from(&mut data.as_slice()).unwrap();
169 assert_eq!(ams_net_id.net_id, [192, 168, 1, 1, 1, 1]);
170 }
171
172 #[test]
173 fn ams_address_new_test() {
174 let ams_net_id = AmsNetId::from_str("192.168.1.1.1.1").unwrap();
175 let port = 30000;
176 let ams_address = AmsAddress::new(ams_net_id.clone(), port);
177
178 assert_eq!(ams_address.port, port);
179 assert_eq!(ams_address.ams_net_id.net_id, ams_net_id.net_id);
180 }
181
182 #[test]
183 fn ams_address_write_to_test() {
184 let ams_net_id = AmsNetId::from_str("192.168.1.1.1.1").unwrap();
185 let port = 30000;
186 let ams_address = AmsAddress::new(ams_net_id.clone(), port);
187
188 let mut buffer: Vec<u8> = Vec::new();
189 ams_address.write_to(&mut buffer).unwrap();
190
191 assert_eq!(buffer, [192, 168, 1, 1, 1, 1, 48, 117]);
192 }
193
194 #[test]
195 fn ams_address_read_from_test() {
196 let data: Vec<u8> = vec![192, 168, 1, 1, 1, 1, 48, 117];
197 let ams_address = AmsAddress::read_from(&mut data.as_slice()).unwrap();
198 assert_eq!(ams_address.ams_net_id.net_id, [192, 168, 1, 1, 1, 1]);
199 assert_eq!(ams_address.port, 30000);
200 }
201
202 #[test]
203 fn ams_address_from_string_test() {
204 let s = "169.0.0.1:45932";
205 let ams_address = AmsAddress::from_str(s).unwrap();
206 assert_eq!(ams_address.ams_net_id.net_id, [169, 0, 0, 1, 1, 1]);
207 assert_eq!(ams_address.port, 45932);
208 }
209}