Add macros to impl concentrate enum and json
This commit is contained in:
parent
f43592c01f
commit
a4b7f100a8
@ -33,7 +33,7 @@ fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|||||||
let name = &field.ident;
|
let name = &field.ident;
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
Encoder::encode(&self.#name, writer);
|
crate::Encoder::encode(&self.#name, writer);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ fn impl_encoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn impl_decoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
fn impl_decoder_trait(name: &Ident, fields: &Fields) -> TokenStream2 {
|
||||||
let decode = quote_field(fields, |field| {
|
let decode = quote_field(fields, |_field| {
|
||||||
quote! {
|
quote! {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
//! assert_eq!(expected_message, Message::from_json(json).unwrap());
|
//! assert_eq!(expected_message, Message::from_json(json).unwrap());
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
use crate::impl_json_encoder_decoder;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Error;
|
use serde_json::Error;
|
||||||
|
|
||||||
@ -243,6 +244,8 @@ impl Message {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_json_encoder_decoder!(Message);
|
||||||
|
|
||||||
pub struct MessageBuilder {
|
pub struct MessageBuilder {
|
||||||
current: Message,
|
current: Message,
|
||||||
root: Option<Message>,
|
root: Option<Message>,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
|
||||||
use crate::chat::Message;
|
use crate::chat::Message;
|
||||||
|
use crate::impl_enum_encoder_decoder;
|
||||||
use crate::DecodeError;
|
use crate::DecodeError;
|
||||||
use crate::Decoder;
|
use crate::Decoder;
|
||||||
use crate::Encoder;
|
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::Packet;
|
||||||
use nbt::CompoundTag;
|
use nbt::CompoundTag;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
@ -111,6 +111,8 @@ pub enum MessagePosition {
|
|||||||
HotBar,
|
HotBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_enum_encoder_decoder!(MessagePosition);
|
||||||
|
|
||||||
impl ClientBoundChatMessage {
|
impl ClientBoundChatMessage {
|
||||||
pub fn new(message: Message, position: MessagePosition) -> GameClientBoundPacket {
|
pub fn new(message: Message, position: MessagePosition) -> GameClientBoundPacket {
|
||||||
let chat_message = ClientBoundChatMessage { message, position };
|
let chat_message = ClientBoundChatMessage { message, position };
|
||||||
@ -139,6 +141,8 @@ pub enum GameMode {
|
|||||||
Hardcore = 8,
|
Hardcore = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_enum_encoder_decoder!(GameMode);
|
||||||
|
|
||||||
impl JoinGame {
|
impl JoinGame {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
entity_id: u32,
|
entity_id: u32,
|
||||||
|
@ -6,8 +6,7 @@ use std::io;
|
|||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
|
|
||||||
use byteorder::WriteBytesExt;
|
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
|
||||||
use mc_varint::{VarIntRead, VarIntWrite};
|
use mc_varint::{VarIntRead, VarIntWrite};
|
||||||
use serde_json::error::Error as JsonError;
|
use serde_json::error::Error as JsonError;
|
||||||
use uuid::parser::ParseError as UuidParseError;
|
use uuid::parser::ParseError as UuidParseError;
|
||||||
@ -16,7 +15,6 @@ use crate::chat::Message;
|
|||||||
use nbt::decode::TagDecodeError;
|
use nbt::decode::TagDecodeError;
|
||||||
use nbt::CompoundTag;
|
use nbt::CompoundTag;
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub mod chat;
|
pub mod chat;
|
||||||
@ -137,23 +135,8 @@ trait Decoder {
|
|||||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError>;
|
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait adds additional helper methods for `Read` to read protocol data.
|
|
||||||
trait PacketRead {
|
|
||||||
fn read_bool(&mut self) -> Result<bool, DecodeError>;
|
|
||||||
|
|
||||||
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError>;
|
|
||||||
|
|
||||||
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
|
||||||
|
|
||||||
fn read_chat_message(&mut self) -> Result<Message, DecodeError>;
|
|
||||||
|
|
||||||
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError>;
|
|
||||||
|
|
||||||
fn read_compound_tag(&mut self) -> Result<CompoundTag, DecodeError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait adds additional helper methods for `Write` to write protocol data.
|
/// Trait adds additional helper methods for `Write` to write protocol data.
|
||||||
trait PacketWrite {
|
trait EncoderWriteExt {
|
||||||
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError>;
|
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError>;
|
||||||
|
|
||||||
fn write_string(&mut self, value: &str, max_length: u32) -> Result<(), EncodeError>;
|
fn write_string(&mut self, value: &str, max_length: u32) -> Result<(), EncodeError>;
|
||||||
@ -167,57 +150,22 @@ trait PacketWrite {
|
|||||||
fn write_compound_tag(&mut self, value: &CompoundTag) -> Result<(), EncodeError>;
|
fn write_compound_tag(&mut self, value: &CompoundTag) -> Result<(), EncodeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read> PacketRead for R {
|
/// Trait adds additional helper methods for `Read` to read protocol data.
|
||||||
fn read_bool(&mut self) -> Result<bool, DecodeError> {
|
trait DecoderReadExt {
|
||||||
match self.read_u8()? {
|
fn read_bool(&mut self) -> Result<bool, DecodeError>;
|
||||||
0 => Ok(false),
|
|
||||||
1 => Ok(true),
|
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError>;
|
||||||
_ => Err(DecodeError::NonBoolValue),
|
|
||||||
}
|
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError>;
|
||||||
|
|
||||||
|
fn read_chat_message(&mut self) -> Result<Message, DecodeError>;
|
||||||
|
|
||||||
|
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError>;
|
||||||
|
|
||||||
|
fn read_compound_tag(&mut self) -> Result<CompoundTag, DecodeError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError> {
|
impl<W: Write> EncoderWriteExt for W {
|
||||||
let length = self.read_var_i32()? as u32;
|
|
||||||
|
|
||||||
if length > max_length as u32 {
|
|
||||||
return Err(DecodeError::StringTooLong { length, max_length });
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf = vec![0; length as usize];
|
|
||||||
self.read_exact(&mut buf)?;
|
|
||||||
|
|
||||||
Ok(String::from_utf8(buf)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError> {
|
|
||||||
let length = self.read_var_i32()?;
|
|
||||||
|
|
||||||
let mut buf = vec![0; length as usize];
|
|
||||||
self.read_exact(&mut buf)?;
|
|
||||||
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_chat_message(&mut self) -> Result<Message, DecodeError> {
|
|
||||||
let json = self.read_string(STRING_MAX_LENGTH)?;
|
|
||||||
let message = Message::from_json(&json)?;
|
|
||||||
|
|
||||||
Ok(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError> {
|
|
||||||
let type_id = self.read_u8()?;
|
|
||||||
let result = FromPrimitive::from_u8(type_id);
|
|
||||||
|
|
||||||
result.ok_or_else(|| DecodeError::UnknownEnumType { type_id })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_compound_tag(&mut self) -> Result<CompoundTag, DecodeError> {
|
|
||||||
Ok(nbt::decode::read_compound_tag(self)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<W: Write> PacketWrite for W {
|
|
||||||
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError> {
|
fn write_bool(&mut self, value: bool) -> Result<(), EncodeError> {
|
||||||
if value {
|
if value {
|
||||||
self.write_u8(1)?;
|
self.write_u8(1)?;
|
||||||
@ -266,7 +214,55 @@ impl<W: Write> PacketWrite for W {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace primitive impls with macros.
|
impl<R: Read> DecoderReadExt for R {
|
||||||
|
fn read_bool(&mut self) -> Result<bool, DecodeError> {
|
||||||
|
match self.read_u8()? {
|
||||||
|
0 => Ok(false),
|
||||||
|
1 => Ok(true),
|
||||||
|
_ => Err(DecodeError::NonBoolValue),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, max_length: u32) -> Result<String, DecodeError> {
|
||||||
|
let length = self.read_var_i32()? as u32;
|
||||||
|
|
||||||
|
if length > max_length as u32 {
|
||||||
|
return Err(DecodeError::StringTooLong { length, max_length });
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = vec![0; length as usize];
|
||||||
|
self.read_exact(&mut buf)?;
|
||||||
|
|
||||||
|
Ok(String::from_utf8(buf)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byte_array(&mut self) -> Result<Vec<u8>, DecodeError> {
|
||||||
|
let length = self.read_var_i32()?;
|
||||||
|
|
||||||
|
let mut buf = vec![0; length as usize];
|
||||||
|
self.read_exact(&mut buf)?;
|
||||||
|
|
||||||
|
Ok(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_chat_message(&mut self) -> Result<Message, DecodeError> {
|
||||||
|
let json = self.read_string(STRING_MAX_LENGTH)?;
|
||||||
|
let message = Message::from_json(&json)?;
|
||||||
|
|
||||||
|
Ok(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_enum<T: FromPrimitive>(&mut self) -> Result<T, DecodeError> {
|
||||||
|
let type_id = self.read_u8()?;
|
||||||
|
let result = FromPrimitive::from_u8(type_id);
|
||||||
|
|
||||||
|
result.ok_or_else(|| DecodeError::UnknownEnumType { type_id })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_compound_tag(&mut self) -> Result<CompoundTag, DecodeError> {
|
||||||
|
Ok(nbt::decode::read_compound_tag(self)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Encoder for u8 {
|
impl Encoder for u8 {
|
||||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
@ -366,20 +362,6 @@ impl Decoder for bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ToPrimitive> Encoder for T {
|
|
||||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
|
||||||
Ok(writer.write_enum(self)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ToPrimitive> Decoder for T {
|
|
||||||
type Output = Self;
|
|
||||||
|
|
||||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
|
||||||
Ok(reader.read_enum())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encoder for Vec<u8> {
|
impl Encoder for Vec<u8> {
|
||||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
||||||
Ok(writer.write_byte_array(self)?)
|
Ok(writer.write_byte_array(self)?)
|
||||||
@ -404,8 +386,8 @@ impl Decoder for Uuid {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
||||||
let buf = [0; 16];
|
let mut buf = [0; 16];
|
||||||
reader.read_exact(&buf)?;
|
reader.read_exact(&mut buf)?;
|
||||||
|
|
||||||
Ok(Uuid::from_bytes(buf))
|
Ok(Uuid::from_bytes(buf))
|
||||||
}
|
}
|
||||||
@ -453,20 +435,45 @@ impl Decoder for Vec<CompoundTag> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Serialize> Encoder for T {
|
#[macro_export]
|
||||||
fn encode<W: Write>(&self, writer: &mut W) -> Result<(), EncodeError> {
|
macro_rules! impl_enum_encoder_decoder (
|
||||||
|
($ty: ident) => (
|
||||||
|
impl crate::Encoder for $ty {
|
||||||
|
fn encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), crate::EncodeError> {
|
||||||
|
Ok(crate::EncoderWriteExt::write_enum(writer, self)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::Decoder for $ty {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn decode<R: std::io::Read>(reader: &mut R) -> Result<Self::Output, crate::DecodeError> {
|
||||||
|
Ok(crate::DecoderReadExt::read_enum(reader)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_json_encoder_decoder (
|
||||||
|
($ty: ident) => (
|
||||||
|
impl crate::Encoder for $ty {
|
||||||
|
fn encode<W: std::io::Write>(&self, writer: &mut W) -> Result<(), crate::EncodeError> {
|
||||||
let json = serde_json::to_string(self)?;
|
let json = serde_json::to_string(self)?;
|
||||||
writer.write_string(&json, STRING_MAX_LENGTH)?;
|
crate::EncoderWriteExt::write_string(writer, &json, crate::STRING_MAX_LENGTH)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T: Deserialize<'de>> Decoder for T {
|
impl crate::Decoder for $ty {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn decode<R: Read>(reader: &mut R) -> Result<Self::Output, DecodeError> {
|
fn decode<R: std::io::Read>(reader: &mut R) -> Result<Self::Output, crate::DecodeError> {
|
||||||
let json = reader.read_string(STRING_MAX_LENGTH)?;
|
let json = crate::DecoderReadExt::read_string(reader, crate::STRING_MAX_LENGTH)?;
|
||||||
serde_json::from_str(&json)?
|
|
||||||
|
Ok(serde_json::from_str(&json)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::chat::Message;
|
use crate::chat::Message;
|
||||||
use crate::DecodeError;
|
use crate::DecodeError;
|
||||||
use crate::Decoder;
|
use crate::Decoder;
|
||||||
use crate::Encoder;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::chat::Message;
|
use crate::chat::Message;
|
||||||
|
use crate::impl_json_encoder_decoder;
|
||||||
use crate::DecodeError;
|
use crate::DecodeError;
|
||||||
use crate::Decoder;
|
use crate::Decoder;
|
||||||
use minecraft_protocol_derive::Packet;
|
use minecraft_protocol_derive::Packet;
|
||||||
@ -104,6 +105,8 @@ pub struct StatusResponse {
|
|||||||
pub server_status: ServerStatus,
|
pub server_status: ServerStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_json_encoder_decoder!(ServerStatus);
|
||||||
|
|
||||||
impl StatusResponse {
|
impl StatusResponse {
|
||||||
pub fn new(server_status: ServerStatus) -> StatusClientBoundPacket {
|
pub fn new(server_status: ServerStatus) -> StatusClientBoundPacket {
|
||||||
let status_response = StatusResponse { server_status };
|
let status_response = StatusResponse { server_status };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user