Apply suggested rustfmt and clippy changes.
parent
5302c04fa4
commit
bdeb8bb6a4
|
@ -0,0 +1,8 @@
|
|||
format_code_in_doc_comments = true
|
||||
match_block_trailing_comma = true
|
||||
max_width = 120
|
||||
newline_style = "Native"
|
||||
normalize_comments = true
|
||||
normalize_doc_attributes = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
112
src/main.rs
112
src/main.rs
|
@ -1,3 +1,4 @@
|
|||
#![allow(incomplete_features)]
|
||||
#![feature(const_generics)]
|
||||
#![feature(never_type)]
|
||||
|
||||
|
@ -9,23 +10,30 @@ use crate::net::protocol::state::handshake::Handshake;
|
|||
use crate::net::protocol::state::login::Login;
|
||||
use crate::net::protocol::state::play::Play;
|
||||
use crate::net::protocol::state::status::Status;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use std::io;
|
||||
use std::net::IpAddr;
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
use clap::{App, load_yaml};
|
||||
use clap::{load_yaml, App};
|
||||
|
||||
let yaml = load_yaml!("cli.yml");
|
||||
let args = App::from_yaml(yaml).get_matches();
|
||||
let host: IpAddr = args.value_of("host").unwrap_or("::").parse()
|
||||
let host: IpAddr = args
|
||||
.value_of("host")
|
||||
.unwrap_or("::")
|
||||
.parse()
|
||||
.expect("Invalid host IP address.");
|
||||
let port: u16 = args.value_of("port").unwrap_or("25565").parse()
|
||||
let port: u16 = args
|
||||
.value_of("port")
|
||||
.unwrap_or("25565")
|
||||
.parse()
|
||||
.expect("Port must be an integer between 1 an 65535.");
|
||||
|
||||
let listener = TcpListener::bind((host, port)).await
|
||||
.expect(&format!("Failed to bind to {}:{}.", host, port));
|
||||
let listener = TcpListener::bind((host, port))
|
||||
.await
|
||||
.unwrap_or_else(|_| panic!("Failed to bind to {}:{}.", host, port));
|
||||
|
||||
listen(listener).await;
|
||||
|
||||
|
@ -39,7 +47,7 @@ async fn listen(mut listener: TcpListener) {
|
|||
Err(e) => {
|
||||
eprintln!("Failed to accept client: {:?}", e);
|
||||
continue;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
tokio::spawn(accept_connection(socket));
|
||||
|
@ -51,8 +59,12 @@ async fn accept_connection(socket: TcpStream) {
|
|||
|
||||
eprintln!("Client connected.");
|
||||
match interact_handshake(con).await {
|
||||
Err(err) => { eprintln!("Client disconnected with error: {:?}", err); },
|
||||
Ok(_) => { eprintln!("Client disconnected without error."); }
|
||||
Err(err) => {
|
||||
eprintln!("Client disconnected with error: {:?}", err);
|
||||
},
|
||||
Ok(_) => {
|
||||
eprintln!("Client disconnected without error.");
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,9 +81,9 @@ async fn interact_handshake(mut con: Connection<Handshake>) -> io::Result<()> {
|
|||
|
||||
match handshake.next_state {
|
||||
Status => interact_status(con.into_status()).await,
|
||||
Login => interact_login(con.into_login()).await
|
||||
Login => interact_login(con.into_login()).await,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,15 +104,16 @@ async fn interact_status(mut con: Connection<Status>) -> io::Result<()> {
|
|||
online: 0,
|
||||
sample: Vec::new(),
|
||||
},
|
||||
description: Chat { text: "Hello, world!".to_string() },
|
||||
description: Chat {
|
||||
text: "Hello, world!".to_string(),
|
||||
},
|
||||
favicon: None,
|
||||
}
|
||||
})).await?;
|
||||
},
|
||||
}))
|
||||
.await?;
|
||||
},
|
||||
Serverbound::Ping(ping) => {
|
||||
con.write(&Clientbound::Pong(Pong {
|
||||
payload: ping.payload
|
||||
})).await?;
|
||||
con.write(&Clientbound::Pong(Pong { payload: ping.payload })).await?;
|
||||
|
||||
// The status ping is now over so the server ends the connection.
|
||||
return Ok(());
|
||||
|
@ -113,30 +126,35 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
use crate::net::protocol::state::login::*;
|
||||
|
||||
let name = match con.read().await? {
|
||||
Serverbound::LoginStart(login_start) => {
|
||||
login_start.name
|
||||
},
|
||||
Serverbound::LoginStart(login_start) => login_start.name,
|
||||
_ => {
|
||||
con.write(&Clientbound::Disconnect(Disconnect {
|
||||
reason: Chat { text: "Unexpected packet (expected Login Start).".to_string() }
|
||||
})).await?;
|
||||
reason: Chat {
|
||||
text: "Unexpected packet (expected Login Start).".to_string(),
|
||||
},
|
||||
}))
|
||||
.await?;
|
||||
return mk_err("Unexpected packet (expected Login Start).");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "encryption")]
|
||||
{
|
||||
use rand::Rng;
|
||||
use rand::rngs::OsRng;
|
||||
use rsa::{RSAPrivateKey, PaddingScheme};
|
||||
use rand::Rng;
|
||||
use rsa::{PaddingScheme, RSAPrivateKey};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
let mut public_key = Vec::new();
|
||||
File::open("private/pub.der").expect("missing public key").read_to_end(&mut public_key)?;
|
||||
File::open("private/pub.der")
|
||||
.expect("missing public key")
|
||||
.read_to_end(&mut public_key)?;
|
||||
|
||||
let mut private_key = Vec::new();
|
||||
File::open("private/priv.der").expect("missing private key").read_to_end(&mut private_key)?;
|
||||
File::open("private/priv.der")
|
||||
.expect("missing private key")
|
||||
.read_to_end(&mut private_key)?;
|
||||
|
||||
let key = RSAPrivateKey::from_pkcs1(&private_key).expect("Invalid private key.");
|
||||
|
||||
|
@ -150,13 +168,14 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
server_id: server_id.to_string().into_boxed_str(),
|
||||
public_key: public_key.clone().into_boxed_slice(),
|
||||
verify_token: verify_token.clone().into_boxed_slice(),
|
||||
})).await?;
|
||||
}))
|
||||
.await?;
|
||||
|
||||
let secret = match con.read().await? {
|
||||
Serverbound::EncryptionResponse(encryption_response) => {
|
||||
let token = key.decrypt(PaddingScheme::PKCS1v15Encrypt,
|
||||
&encryption_response.verify_token)
|
||||
.expect("Failed to decrypt verify token.");
|
||||
let token = key
|
||||
.decrypt(PaddingScheme::PKCS1v15Encrypt, &encryption_response.verify_token)
|
||||
.expect("Failed to decrypt verify token.");
|
||||
if token.as_slice() != verify_token.as_slice() {
|
||||
return mk_err("Incorrect verify token.");
|
||||
}
|
||||
|
@ -166,7 +185,7 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
},
|
||||
_ => {
|
||||
return mk_err("Unexpected packet (expected Encryption Response).");
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
con = con.set_encryption(&secret).expect("Failed to set encryption.");
|
||||
|
@ -175,7 +194,7 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
{
|
||||
let server_hash = {
|
||||
let server_hash_bytes = {
|
||||
use sha1::{Sha1, Digest};
|
||||
use sha1::{Digest, Sha1};
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(server_id.as_bytes());
|
||||
hasher.update(&secret);
|
||||
|
@ -188,10 +207,19 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
|
||||
use reqwest::Client;
|
||||
|
||||
println!("{:?}", Client::new().get("https://sessionserver.mojang.com/session/minecraft/hasJoined")
|
||||
.header("Content-Type", "application/json")
|
||||
.query(&[("username", name.clone()), ("serverId", server_hash.into_boxed_str())])
|
||||
.send().await.expect("Request failed.").text().await.unwrap());
|
||||
println!(
|
||||
"{:?}",
|
||||
Client::new()
|
||||
.get("https://sessionserver.mojang.com/session/minecraft/hasJoined")
|
||||
.header("Content-Type", "application/json")
|
||||
.query(&[("username", name.clone()), ("serverId", server_hash.into_boxed_str())])
|
||||
.send()
|
||||
.await
|
||||
.expect("Request failed.")
|
||||
.text()
|
||||
.await
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +229,8 @@ async fn interact_login(mut con: Connection<Login>) -> io::Result<()> {
|
|||
con.write(&Clientbound::LoginSuccess(LoginSuccess {
|
||||
uuid: uuid::Uuid::nil(),
|
||||
username: name,
|
||||
})).await?;
|
||||
}))
|
||||
.await?;
|
||||
|
||||
interact_play(con.into_play()).await
|
||||
}
|
||||
|
@ -210,8 +239,11 @@ async fn interact_play(mut con: Connection<Play>) -> io::Result<()> {
|
|||
use crate::net::protocol::state::play::*;
|
||||
|
||||
con.write(&Clientbound::Disconnect(Disconnect {
|
||||
reason: Chat { text: "Goodbye!".to_string() }
|
||||
})).await?;
|
||||
reason: Chat {
|
||||
text: "Goodbye!".to_string(),
|
||||
},
|
||||
}))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
mod packet_format;
|
||||
mod stream;
|
||||
|
||||
use crate::net::connection::packet_format::PacketFormat;
|
||||
use crate::net::connection::packet_format::default::DefaultPacketFormat;
|
||||
use crate::net::connection::packet_format::PacketFormat;
|
||||
use crate::net::connection::stream::Stream;
|
||||
use crate::net::protocol::packet_map::PacketMap;
|
||||
use crate::net::protocol::state::ProtocolState;
|
||||
use crate::net::protocol::state::handshake::Handshake;
|
||||
use crate::net::protocol::state::login::Login;
|
||||
use crate::net::protocol::state::play::Play;
|
||||
use crate::net::protocol::state::status::Status;
|
||||
use crate::net::protocol::state::ProtocolState;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use tokio::io::BufStream;
|
||||
|
@ -48,6 +48,7 @@ impl<St: ProtocolState> Connection<St> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn into_disconnected(self) -> Connection<!> {
|
||||
self.into_state()
|
||||
}
|
||||
|
@ -75,15 +76,16 @@ impl Connection<Login> {
|
|||
#[cfg(feature = "compression")]
|
||||
pub async fn set_compression(&mut self, threshold: Option<u32>) -> io::Result<()> {
|
||||
use crate::net::connection::packet_format::compressed::CompressedPacketFormat;
|
||||
use crate::net::serialize::VarInt;
|
||||
use crate::net::protocol::state::login::{Clientbound, SetCompression};
|
||||
use crate::net::serialize::VarInt;
|
||||
|
||||
// Tell the client about the new compression threshold,
|
||||
// using a packet compressed with the old compression threshold.
|
||||
self.write(&Clientbound::SetCompression(SetCompression {
|
||||
// A negative threshold will disable compression.
|
||||
threshold: VarInt(threshold.map(|x| x as i32).unwrap_or(-1)),
|
||||
})).await?;
|
||||
}))
|
||||
.await?;
|
||||
|
||||
// Further packets will use the new compression threshold.
|
||||
match threshold {
|
||||
|
@ -92,19 +94,20 @@ impl Connection<Login> {
|
|||
},
|
||||
None => {
|
||||
self.fmt = Box::new(DefaultPacketFormat);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// WARNING: This function is not idempontent.
|
||||
/// Calling it twice will result in the underlying stream getting encrypted twice.
|
||||
/// Calling it twice will result in the underlying stream getting encrypted
|
||||
/// twice.
|
||||
#[cfg(feature = "encryption")]
|
||||
pub fn set_encryption(self, secret: &[u8]) -> Result<Self, String> {
|
||||
use cfb8::Cfb8;
|
||||
use cfb8::stream_cipher::NewStreamCipher;
|
||||
use crate::net::connection::stream::encrypted::EncryptedStream;
|
||||
use cfb8::stream_cipher::NewStreamCipher;
|
||||
use cfb8::Cfb8;
|
||||
|
||||
let cipher: Cfb8<aes::Aes128> = Cfb8::new_var(secret, secret).map_err(|err| err.to_string())?;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ pub async fn read_varint(src: &mut Reader) -> io::Result<(usize, i32)> {
|
|||
let mut acc = 0;
|
||||
while num_read < 5 {
|
||||
let byte = src.read_u8().await?;
|
||||
acc |= ((byte & 0b01111111) as i32) << num_read * 7;
|
||||
acc |= ((byte & 0b01111111) as i32) << (num_read * 7);
|
||||
|
||||
num_read += 1;
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::net::connection::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
|
||||
use async_trait::async_trait;
|
||||
use crate::net::connection::packet_format::
|
||||
{PacketFormat, Reader, Writer, MAX_PACKET_SIZE, read_varint};
|
||||
use std::boxed::Box;
|
||||
use std::io;
|
||||
|
||||
|
@ -10,9 +9,7 @@ pub struct CompressedPacketFormat {
|
|||
|
||||
impl CompressedPacketFormat {
|
||||
pub fn new(threshold: usize) -> Self {
|
||||
Self {
|
||||
threshold: threshold,
|
||||
}
|
||||
Self { threshold }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,9 +84,10 @@ impl PacketFormat for CompressedPacketFormat {
|
|||
// in case the output data ends up larger than the input data
|
||||
// (e.g. due to the zlib header).
|
||||
// FIXME: Further research to figure out the exact maximum capacity necessary.
|
||||
// Perhaps you only need space for the header and the data itself can't get bigger?
|
||||
// And what is the limit to how much bigger the data will get?
|
||||
// Currently I don't actually know for a fact that this won't ever drop data.
|
||||
// Perhaps you only need space for the header and the data itself can't get
|
||||
// bigger? And what is the limit to how much bigger the data will
|
||||
// get? Currently I don't actually know for a fact that this won't
|
||||
// ever drop data.
|
||||
let mut compressed = Vec::with_capacity(1024 + data.len());
|
||||
Compress::new(flate2::Compression::best(), true)
|
||||
.compress_vec(data, &mut compressed, FlushCompress::Finish)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::net::connection::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
|
||||
use async_trait::async_trait;
|
||||
use crate::net::connection::packet_format::
|
||||
{PacketFormat, Reader, Writer, MAX_PACKET_SIZE, read_varint};
|
||||
use std::boxed::Box;
|
||||
use std::io;
|
||||
|
||||
|
@ -15,10 +14,8 @@ impl PacketFormat for DefaultPacketFormat {
|
|||
if length > MAX_PACKET_SIZE as i32 {
|
||||
return Err(io::Error::new(io::ErrorKind::Other, "Packet was too long.".to_string()));
|
||||
}
|
||||
let length = length as usize;
|
||||
|
||||
let mut buf = Vec::with_capacity(length);
|
||||
buf.resize(length, 0);
|
||||
let mut buf = vec![0; length as usize];
|
||||
src.read_exact(buf.as_mut_slice()).await?;
|
||||
|
||||
Ok(buf.into_boxed_slice())
|
||||
|
|
|
@ -3,5 +3,5 @@ pub mod encrypted;
|
|||
|
||||
use tokio::io::{AsyncRead, AsyncWrite};
|
||||
|
||||
pub trait Stream: AsyncRead + AsyncWrite + Send + Unpin { }
|
||||
impl<S: AsyncRead + AsyncWrite + Send + Unpin> Stream for S { }
|
||||
pub trait Stream: AsyncRead + AsyncWrite + Send + Unpin {}
|
||||
impl<S: AsyncRead + AsyncWrite + Send + Unpin> Stream for S {}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use aes::Aes128;
|
||||
use cfb8::Cfb8;
|
||||
use cfb8::stream_cipher::StreamCipher;
|
||||
use crate::net::connection::stream::Stream;
|
||||
use aes::Aes128;
|
||||
use cfb8::stream_cipher::StreamCipher;
|
||||
use cfb8::Cfb8;
|
||||
use std::pin::Pin;
|
||||
use std::task::Poll;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
use tokio::io::{AsyncRead, AsyncWrite, Result};
|
||||
|
||||
pub struct EncryptedStream {
|
||||
|
@ -16,18 +16,18 @@ pub struct EncryptedStream {
|
|||
impl EncryptedStream {
|
||||
pub fn new(rw: Box<dyn Stream>, cipher: Cfb8<Aes128>) -> Self {
|
||||
Self {
|
||||
rw: rw,
|
||||
cipher: cipher,
|
||||
rw,
|
||||
cipher,
|
||||
write_buf: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&mut self, cx: &mut Context) -> Poll<Result<()>> {
|
||||
// We don't know when the internal writer will be ready,
|
||||
// so we have to coax it into returning "pending" and scheduling an interrupt for us.
|
||||
// Either that, or we finish writing our buffer and flush.
|
||||
// so we have to coax it into returning "pending" and scheduling an interrupt
|
||||
// for us. Either that, or we finish writing our buffer and flush.
|
||||
loop {
|
||||
if self.write_buf.len() == 0 {
|
||||
if self.write_buf.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ impl EncryptedStream {
|
|||
new_buf.copy_from_slice(&self.write_buf[length..]);
|
||||
self.write_buf = new_buf;
|
||||
},
|
||||
other => return other.map(|x| x.map(|_| ()))
|
||||
other => return other.map(|x| x.map(|_| ())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ impl AsyncRead for EncryptedStream {
|
|||
me.cipher.decrypt(&mut buf[..bytes]);
|
||||
Poll::Ready(Ok(bytes))
|
||||
},
|
||||
other => other
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,10 +79,8 @@ impl AsyncWrite for EncryptedStream {
|
|||
let me = Pin::into_inner(self);
|
||||
|
||||
match me.flush(cx) {
|
||||
Poll::Ready(Ok(())) => {
|
||||
Pin::new(&mut me.rw).poll_shutdown(cx)
|
||||
},
|
||||
other => other
|
||||
Poll::Ready(Ok(())) => Pin::new(&mut me.rw).poll_shutdown(cx),
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
pub mod packet_map;
|
||||
pub mod packet;
|
||||
pub mod packet_map;
|
||||
pub mod state;
|
||||
|
|
|
@ -16,7 +16,7 @@ macro_rules! define_packets {
|
|||
deser.read_eof()?;
|
||||
Ok($name {
|
||||
$(
|
||||
$field: $field,
|
||||
$field,
|
||||
)*
|
||||
})
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ impl PacketMap for ! {
|
|||
}
|
||||
|
||||
fn write(&self, _ser: &mut impl PacketSerializer) {
|
||||
match *self { }
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,5 +25,5 @@ macro_rules! define_state {
|
|||
type Clientbound = $cb;
|
||||
type Serverbound = $sb;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{define_packets, define_packet_maps, define_state};
|
||||
use crate::net::serialize::{PacketReadable, PacketWritable, PacketDeserializer, PacketSerializer, VarInt};
|
||||
use crate::net::serialize::{PacketDeserializer, PacketReadable, PacketSerializer, PacketWritable, VarInt};
|
||||
use crate::{define_packet_maps, define_packets, define_state};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum HandshakeNextState {
|
||||
|
@ -14,7 +14,7 @@ impl PacketReadable for HandshakeNextState {
|
|||
Ok(match deser.read::<VarInt>()?.into() {
|
||||
1 => Status,
|
||||
2 => Login,
|
||||
n => return Err(format!("Invalid next protocol state in handshake: {}", n))
|
||||
n => return Err(format!("Invalid next protocol state in handshake: {}", n)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{define_packets, define_packet_maps, define_state};
|
||||
use crate::net::chat::Chat;
|
||||
use crate::net::serialize::{Rest, VarInt};
|
||||
use crate::{define_packet_maps, define_packets, define_state};
|
||||
use uuid::Uuid;
|
||||
|
||||
define_packets! {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{define_packets, define_packet_maps, define_state};
|
||||
use crate::net::chat::Chat;
|
||||
use crate::{define_packet_maps, define_packets, define_state};
|
||||
|
||||
// TODO: This protocol state isn't even close to entirely mapped.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{define_packets, define_packet_maps, define_state};
|
||||
use crate::net::chat::Chat;
|
||||
use crate::net::serialize::{PacketJson};
|
||||
use crate::net::serialize::PacketJson;
|
||||
use crate::{define_packet_maps, define_packets, define_state};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
|
@ -22,7 +22,7 @@ impl PacketJson for ResponsePlayersSample {}
|
|||
pub struct ResponsePlayers {
|
||||
pub max: u32,
|
||||
pub online: u32,
|
||||
pub sample: Vec<ResponsePlayersSample>
|
||||
pub sample: Vec<ResponsePlayersSample>,
|
||||
}
|
||||
impl PacketJson for ResponsePlayers {}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::{From, Into};
|
||||
use uuid::Uuid;
|
||||
|
@ -38,11 +38,8 @@ pub struct VecPacketDeserializer<'a> {
|
|||
}
|
||||
|
||||
impl VecPacketDeserializer<'_> {
|
||||
pub fn new<'a>(data: &'a [u8]) -> VecPacketDeserializer<'a> {
|
||||
VecPacketDeserializer {
|
||||
data: data,
|
||||
index: 0,
|
||||
}
|
||||
pub fn new(data: &[u8]) -> VecPacketDeserializer<'_> {
|
||||
VecPacketDeserializer { data, index: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +89,7 @@ impl PacketReadable for bool {
|
|||
match value {
|
||||
0x00 => Ok(false),
|
||||
0x01 => Ok(true),
|
||||
n => Err(format!("{:0X} is not a valid boolean.", n))
|
||||
n => Err(format!("{:0X} is not a valid boolean.", n)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +155,7 @@ macro_rules! impl_varnum {
|
|||
}
|
||||
|
||||
// Make space for the rest of the bits.
|
||||
acc = acc << 7;
|
||||
acc <<= 7;
|
||||
}
|
||||
|
||||
Err(format!("VarNum was more than {} bytes.", $length))
|
||||
|
@ -170,7 +167,7 @@ macro_rules! impl_varnum {
|
|||
let mut value = self.0;
|
||||
loop {
|
||||
let mut temp = (value & 0b01111111) as u8;
|
||||
value = value >> 7;
|
||||
value >>= 7;
|
||||
if value != 0 {
|
||||
temp |= 0b10000000;
|
||||
}
|
||||
|
@ -201,10 +198,8 @@ impl PacketReadable for Vec<u8> {
|
|||
if length < 0 {
|
||||
return Err("Array or string length cannot be negative.".to_string());
|
||||
}
|
||||
let length = length as usize;
|
||||
|
||||
let mut it = Vec::with_capacity(length);
|
||||
it.resize(length, 0);
|
||||
let mut it = vec![0; length as usize];
|
||||
deser.read_exact(it.as_mut_slice())?;
|
||||
|
||||
Ok(it)
|
||||
|
@ -286,12 +281,12 @@ impl PacketWritable for &Uuid {
|
|||
}
|
||||
}
|
||||
|
||||
/// A marker trait indicating that a JSON-serialiable type should be serialized as JSON in packets.
|
||||
/// Most primitive types are already serializable as JSON,
|
||||
/// A marker trait indicating that a JSON-serialiable type should be serialized
|
||||
/// as JSON in packets. Most primitive types are already serializable as JSON,
|
||||
/// but we explicitly *don't* want to serialize them as JSON in packets.
|
||||
pub trait PacketJson { }
|
||||
pub trait PacketJson {}
|
||||
|
||||
impl PacketJson for crate::net::chat::Chat { }
|
||||
impl PacketJson for crate::net::chat::Chat {}
|
||||
|
||||
impl<S: DeserializeOwned + PacketJson + Sized> PacketReadable for S {
|
||||
fn read(deser: &mut impl PacketDeserializer) -> Result<Self, String> {
|
||||
|
@ -307,20 +302,17 @@ impl<S: PacketJson + Serialize> PacketWritable for &S {
|
|||
}
|
||||
|
||||
// Although according to my organizational scheme, this should go first,
|
||||
// it goes last anyway because constant generics break Atom's syntax highlighting
|
||||
// for all code below it.
|
||||
// it goes last anyway because constant generics break Atom's syntax
|
||||
// highlighting for all code below it.
|
||||
|
||||
impl<const N: usize> PacketReadable for [u8; N] {
|
||||
fn read(deser: &mut impl PacketDeserializer) -> Result<Self, String> {
|
||||
use std::convert::TryInto;
|
||||
|
||||
let mut buf = [0; N];
|
||||
deser.read_exact(&mut buf)?;
|
||||
Ok(buf.try_into().unwrap())
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<const N: usize> PacketWritable for [u8; N] {
|
||||
fn write(self, ser: &mut impl PacketSerializer) {
|
||||
ser.write_exact(&self);
|
||||
|
|
Loading…
Reference in New Issue