1#![feature(error_generic_member_access)]
14
15use std::{fmt::Display, net::SocketAddr, str::FromStr};
16
17pub mod common;
18#[cfg(feature = "connecting")]
19pub mod connect;
20#[cfg(feature = "packets")]
21pub mod packets;
22pub mod read;
23pub mod resolver;
24pub mod write;
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
39pub struct ServerAddress {
40 pub host: String,
41 pub port: u16,
42}
43
44impl TryFrom<&str> for ServerAddress {
45 type Error = String;
46
47 fn try_from(string: &str) -> Result<Self, Self::Error> {
50 if string.is_empty() {
51 return Err("Empty string".to_string());
52 }
53 let mut parts = string.split(':');
54 let host = parts.next().ok_or("No host specified")?.to_string();
55 let port = parts.next().unwrap_or("25565");
57 let port = u16::from_str(port).map_err(|_| "Invalid port specified")?;
58 Ok(ServerAddress { host, port })
59 }
60}
61impl TryFrom<String> for ServerAddress {
62 type Error = String;
63
64 fn try_from(string: String) -> Result<Self, Self::Error> {
65 ServerAddress::try_from(string.as_str())
66 }
67}
68
69impl From<SocketAddr> for ServerAddress {
70 fn from(addr: SocketAddr) -> Self {
74 ServerAddress {
75 host: addr.ip().to_string(),
76 port: addr.port(),
77 }
78 }
79}
80
81impl Display for ServerAddress {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 write!(f, "{}:{}", self.host, self.port)
84 }
85}
86
87impl<'de> serde::Deserialize<'de> for ServerAddress {
90 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91 where
92 D: serde::Deserializer<'de>,
93 {
94 let string = String::deserialize(deserializer)?;
95 ServerAddress::try_from(string.as_str()).map_err(serde::de::Error::custom)
96 }
97}
98
99impl serde::Serialize for ServerAddress {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: serde::Serializer,
105 {
106 serializer.serialize_str(&self.to_string())
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use std::io::Cursor;
113
114 use uuid::Uuid;
115
116 use crate::{
117 packets::{
118 Packet,
119 game::s_chat::{LastSeenMessagesUpdate, ServerboundChat},
120 login::{ServerboundLoginPacket, s_hello::ServerboundHello},
121 },
122 read::{compression_decoder, read_packet},
123 write::{compression_encoder, serialize_packet, write_packet},
124 };
125
126 #[tokio::test]
127 async fn test_hello_packet() {
128 let packet = ServerboundHello {
129 name: "test".to_string(),
130 profile_id: Uuid::nil(),
131 };
132 let mut stream = Vec::new();
133 write_packet(&packet.into_variant(), &mut stream, None, &mut None)
134 .await
135 .unwrap();
136
137 assert_eq!(
138 stream,
139 [
140 22, 0, 4, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
141 ]
142 );
143
144 let mut stream = Cursor::new(stream);
145
146 let _ = read_packet::<ServerboundLoginPacket, _>(
147 &mut stream,
148 &mut Cursor::new(Vec::new()),
149 None,
150 &mut None,
151 )
152 .await
153 .unwrap();
154 }
155
156 #[tokio::test]
157 async fn test_double_hello_packet() {
158 let packet = ServerboundHello {
159 name: "test".to_string(),
160 profile_id: Uuid::nil(),
161 }
162 .into_variant();
163 let mut stream = Vec::new();
164 write_packet(&packet, &mut stream, None, &mut None)
165 .await
166 .unwrap();
167 write_packet(&packet, &mut stream, None, &mut None)
168 .await
169 .unwrap();
170 let mut stream = Cursor::new(stream);
171
172 let mut buffer = Cursor::new(Vec::new());
173
174 let _ = read_packet::<ServerboundLoginPacket, _>(&mut stream, &mut buffer, None, &mut None)
175 .await
176 .unwrap();
177 let _ = read_packet::<ServerboundLoginPacket, _>(&mut stream, &mut buffer, None, &mut None)
178 .await
179 .unwrap();
180 }
181
182 #[tokio::test]
183 async fn test_read_long_compressed_chat() {
184 let compression_threshold = 256;
185
186 let buf = serialize_packet(
187 &ServerboundChat {
188 message: "a".repeat(256),
189 timestamp: 0,
190 salt: 0,
191 signature: None,
192 last_seen_messages: LastSeenMessagesUpdate::default(),
193 }
194 .into_variant(),
195 )
196 .unwrap();
197
198 let buf = compression_encoder(&buf, compression_threshold).unwrap();
199
200 println!("{:?}", buf);
201
202 compression_decoder(&mut Cursor::new(&buf), compression_threshold).unwrap();
203 }
204}