ads_proto/proto/
ams_address.rs

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]; //Read only the first 6 bytes!
168        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}