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