Finalize Handshake, Status and Login serde
Dieser Commit ist enthalten in:
Ursprung
4efe1aaf36
Commit
2989ac7938
@ -11,4 +11,5 @@ tokio-stream = "0.1"
|
|||||||
serde = { version = "1.0", features = ["derive", "std"] }
|
serde = { version = "1.0", features = ["derive", "std"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
bytes = "1.1"
|
bytes = "1.1"
|
||||||
|
uuid = "0.8"
|
||||||
lixcraft-derive = { path = "lixcraft-derive" }
|
lixcraft-derive = { path = "lixcraft-derive" }
|
87
src/frames.rs
Normale Datei
87
src/frames.rs
Normale Datei
@ -0,0 +1,87 @@
|
|||||||
|
use std::io::ErrorKind;
|
||||||
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
use tokio::io::Error;
|
||||||
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
|
use crate::VarInt;
|
||||||
|
|
||||||
|
pub struct LengthPrefixedFrame {
|
||||||
|
pub max_length: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VarIntReadError {
|
||||||
|
BytesMissing,
|
||||||
|
InvalidData
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LengthPrefixedFrame {
|
||||||
|
fn try_read_var_int(&self, src: &mut BytesMut) -> Result<(VarInt, usize), VarIntReadError> {
|
||||||
|
let src = src.chunk();
|
||||||
|
let mut num_read = 0;
|
||||||
|
let mut result = 0;
|
||||||
|
loop {
|
||||||
|
if src.len() <= num_read {
|
||||||
|
return Err(VarIntReadError::BytesMissing)
|
||||||
|
}
|
||||||
|
let read = src[num_read];
|
||||||
|
let value = i32::from(read & 0b0111_1111);
|
||||||
|
result |= value.overflowing_shl((7 * num_read) as u32).0;
|
||||||
|
|
||||||
|
num_read += 1;
|
||||||
|
|
||||||
|
if num_read > 5 {
|
||||||
|
return Err(VarIntReadError::InvalidData);
|
||||||
|
}
|
||||||
|
if read & 0b1000_0000 == 0 {
|
||||||
|
return if result as usize > self.max_length {
|
||||||
|
Err(VarIntReadError::InvalidData)
|
||||||
|
} else {
|
||||||
|
Ok((VarInt(result), num_read))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoder for LengthPrefixedFrame {
|
||||||
|
type Item = BytesMut;
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||||
|
println!("!");
|
||||||
|
match self.try_read_var_int(src) { //TODO: Packet length maximal 2097151 byte
|
||||||
|
Ok((length, prefix_length)) => {
|
||||||
|
let total_length = prefix_length + usize::from(length);
|
||||||
|
|
||||||
|
if src.len() >= total_length {
|
||||||
|
src.advance(prefix_length);
|
||||||
|
Ok(Some(src.split_to(usize::from(length))))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(VarIntReadError::BytesMissing) => Ok(None),
|
||||||
|
Err(VarIntReadError::InvalidData) => Err(Error::from(ErrorKind::InvalidData))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Encoder<Bytes> for LengthPrefixedFrame {
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
fn encode(&mut self, data: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
||||||
|
dst.reserve(5 + data.len());
|
||||||
|
|
||||||
|
let mut v = data.len();
|
||||||
|
loop {
|
||||||
|
if v & 0x80 == 0 {
|
||||||
|
dst.put_u8(v as u8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.put_u8((v as u8 & 0x7f) | 0x80);
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst.put_slice(&data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
147
src/main.rs
147
src/main.rs
@ -1,18 +1,49 @@
|
|||||||
extern crate core;
|
extern crate core;
|
||||||
|
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
mod packets;
|
pub mod packets;
|
||||||
|
pub mod frames;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
use std::sync::Arc;
|
||||||
|
use bytes::BytesMut;
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
use tokio_util::codec::Framed;
|
||||||
|
use crate::frames::LengthPrefixedFrame;
|
||||||
use crate::packets::handshake::HandshakePacket;
|
use crate::packets::handshake::HandshakePacket;
|
||||||
use crate::serde::{JavaSerializable, VarInt};
|
use crate::serde::{JavaSerializable, VarInt};
|
||||||
|
|
||||||
|
pub struct Server {
|
||||||
|
listener: Arc<TcpListener> //TODO: TcpListener not required from anybody
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RawConnection {
|
||||||
|
pub server: Arc<Server>,
|
||||||
|
pub remote_addr: SocketAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Server {
|
||||||
|
pub async fn new(listen_addr: String) -> Result<Arc<Server>, Box<dyn Error>> {
|
||||||
|
let server = Arc::new(Server {
|
||||||
|
listener : Arc::new(TcpListener::bind(listen_addr).await?)
|
||||||
|
});
|
||||||
|
|
||||||
|
let server_clone = server.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
while let Ok((inbound, addr)) = server_clone.listener.accept().await {
|
||||||
|
tokio::spawn(async move {process_initial(inbound, addr)}.await);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(server)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Shutdown construction! Yay
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let listen_addr = String::from("127.0.0.1:25565");
|
let listen_addr = String::from("127.0.0.1:25565");
|
||||||
@ -28,8 +59,25 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Reason {
|
||||||
|
Disconnected,
|
||||||
|
ConnectionDrop,
|
||||||
|
ProtocolError
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Protocol {
|
||||||
|
packet_handlers: HashMap<VarInt, Box<dyn FnMut(BytesMut) -> Reason>>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_handshake(buf: BytesMut) -> Result<Framed<TcpStream, LengthPrefixedFrame>, Reason> {
|
||||||
|
Err(Reason::Disconnected)
|
||||||
|
}
|
||||||
|
|
||||||
async fn process_initial(stream: TcpStream, _addr: SocketAddr) {
|
async fn process_initial(stream: TcpStream, _addr: SocketAddr) {
|
||||||
|
/*let handshake_protocol = Protocol {
|
||||||
|
packet_handlers: HashMap::from([(VarInt(0), Box::new(handle_handshake) as Box<dyn FnMut(BytesMut) -> Reason>)]),
|
||||||
|
};*/
|
||||||
|
|
||||||
let mut framed = Framed::new(stream, LengthPrefixedFrame {max_length: 263});
|
let mut framed = Framed::new(stream, LengthPrefixedFrame {max_length: 263});
|
||||||
match framed.next().await {
|
match framed.next().await {
|
||||||
Some(Ok(buf)) => {
|
Some(Ok(buf)) => {
|
||||||
@ -49,94 +97,3 @@ async fn process_initial(stream: TcpStream, _addr: SocketAddr) {
|
|||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum VarIntReadError {
|
|
||||||
BytesMissing,
|
|
||||||
InvalidData
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LengthPrefixedFrame {
|
|
||||||
pub max_length: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LengthPrefixedFrame {
|
|
||||||
fn try_read_var_int(&self, src: &mut BytesMut) -> Result<(VarInt, usize), VarIntReadError> {
|
|
||||||
let src = src.chunk();
|
|
||||||
let mut num_read = 0;
|
|
||||||
let mut result = 0;
|
|
||||||
loop {
|
|
||||||
if src.len() <= num_read {
|
|
||||||
return Err(VarIntReadError::BytesMissing)
|
|
||||||
}
|
|
||||||
let read = src[num_read];
|
|
||||||
let value = i32::from(read & 0b0111_1111);
|
|
||||||
result |= value.overflowing_shl((7 * num_read) as u32).0;
|
|
||||||
|
|
||||||
num_read += 1;
|
|
||||||
|
|
||||||
if num_read > 5 {
|
|
||||||
return Err(VarIntReadError::InvalidData);
|
|
||||||
}
|
|
||||||
if read & 0b1000_0000 == 0 {
|
|
||||||
return if result as usize > self.max_length {
|
|
||||||
Err(VarIntReadError::InvalidData)
|
|
||||||
} else {
|
|
||||||
Ok((VarInt(result), num_read))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decoder for LengthPrefixedFrame {
|
|
||||||
type Item = BytesMut;
|
|
||||||
type Error = tokio::io::Error;
|
|
||||||
|
|
||||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
|
||||||
println!("!");
|
|
||||||
match self.try_read_var_int(src) {
|
|
||||||
Ok((length, prefix_length)) => {
|
|
||||||
let total_length = prefix_length + usize::from(length);
|
|
||||||
|
|
||||||
if src.len() >= total_length {
|
|
||||||
src.advance(prefix_length);
|
|
||||||
println!("a1");
|
|
||||||
Ok(Some(src.split_to(usize::from(length))))
|
|
||||||
} else {
|
|
||||||
println!("a2");
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(VarIntReadError::BytesMissing) => {
|
|
||||||
println!("b");
|
|
||||||
Ok(None)
|
|
||||||
},
|
|
||||||
Err(VarIntReadError::InvalidData) => {
|
|
||||||
println!("c");
|
|
||||||
Err(tokio::io::Error::from(ErrorKind::InvalidData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Encoder<Bytes> for LengthPrefixedFrame {
|
|
||||||
type Error = tokio::io::Error;
|
|
||||||
|
|
||||||
fn encode(&mut self, data: Bytes, dst: &mut BytesMut) -> Result<(), Self::Error> {
|
|
||||||
dst.reserve(5 + data.len());
|
|
||||||
|
|
||||||
let mut v = data.len();
|
|
||||||
loop {
|
|
||||||
if v & 0x80 == 0 {
|
|
||||||
dst.put_u8(v as u8);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.put_u8((v as u8 & 0x7f) | 0x80);
|
|
||||||
v >>= 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.put_slice(&data);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,10 @@
|
|||||||
pub mod handshake {
|
pub mod handshake {
|
||||||
use crate::serde::{VarInt, JavaSerializable, NextState};
|
use crate::serde::{VarInt, JavaSerializable, NextState, String255};
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct HandshakePacket {
|
pub struct HandshakePacket {
|
||||||
pub protocol_version: VarInt,
|
pub protocol_version: VarInt,
|
||||||
pub server_address: String,
|
pub server_address: String255,
|
||||||
pub server_port: u16,
|
pub server_port: u16,
|
||||||
pub next_state: NextState
|
pub next_state: NextState
|
||||||
}
|
}
|
||||||
@ -28,8 +28,9 @@ pub mod status {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod login {
|
pub mod login {
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use crate::serde::{VarInt, JavaSerializable, Chat, JavaDeserError};
|
use uuid::Uuid;
|
||||||
|
use crate::serde::{VarInt, JavaSerializable, Chat, JavaDeserError, String20, String16, Identifier, RemainingBytes};
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct DisconnectPacket{
|
pub struct DisconnectPacket{
|
||||||
@ -38,15 +39,15 @@ pub mod login {
|
|||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct EncryptionRequestPacket {
|
pub struct EncryptionRequestPacket {
|
||||||
server_id: String,
|
server_id: String20,
|
||||||
public_key: Vec::<u8>,
|
public_key: Vec::<u8>,
|
||||||
verify_token: Vec::<u8>
|
verify_token: Vec::<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct LoginSuccessPacket {
|
pub struct LoginSuccessPacket {
|
||||||
uuid: String, //TODO: UUID
|
uuid: Uuid,
|
||||||
username: String
|
username: String16
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
@ -57,13 +58,13 @@ pub mod login {
|
|||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct PluginRequestPacket {
|
pub struct PluginRequestPacket {
|
||||||
message_id: VarInt,
|
message_id: VarInt,
|
||||||
channel: String, //TODO: Identifier
|
channel: Identifier,
|
||||||
data: Vec::<u8> //TODO: Length inferred by packet length
|
data: RemainingBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
pub struct LoginStartPacket {
|
pub struct LoginStartPacket {
|
||||||
name: String
|
name: String16
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(JavaSerializable, Debug)]
|
#[derive(JavaSerializable, Debug)]
|
||||||
@ -74,7 +75,7 @@ pub mod login {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PluginResponseSuccessful {
|
pub enum PluginResponseSuccessful {
|
||||||
Successful(Vec<u8>),
|
Successful(RemainingBytes),
|
||||||
Failed
|
Failed
|
||||||
}
|
}
|
||||||
impl JavaSerializable for PluginResponseSuccessful {
|
impl JavaSerializable for PluginResponseSuccessful {
|
||||||
@ -89,7 +90,7 @@ pub mod login {
|
|||||||
match self {
|
match self {
|
||||||
PluginResponseSuccessful::Successful(v) => {
|
PluginResponseSuccessful::Successful(v) => {
|
||||||
true.serialize(buf);
|
true.serialize(buf);
|
||||||
buf.put_slice(v.as_slice())
|
v.serialize(buf);
|
||||||
}
|
}
|
||||||
PluginResponseSuccessful::Failed => false.serialize(buf)
|
PluginResponseSuccessful::Failed => false.serialize(buf)
|
||||||
}
|
}
|
||||||
@ -97,7 +98,7 @@ pub mod login {
|
|||||||
|
|
||||||
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
match bool::deserialize(buf)? {
|
match bool::deserialize(buf)? {
|
||||||
true => Ok(PluginResponseSuccessful::Successful(buf.to_vec())),
|
true => Ok(PluginResponseSuccessful::Successful(RemainingBytes::deserialize(buf)?)),
|
||||||
false => Ok(PluginResponseSuccessful::Failed)
|
false => Ok(PluginResponseSuccessful::Failed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
86
src/serde.rs
86
src/serde.rs
@ -3,6 +3,7 @@ use bytes::{Buf, BufMut, Bytes, BytesMut};
|
|||||||
use crate::serde::JavaDeserError::{InvalidValue, MissingBytes};
|
use crate::serde::JavaDeserError::{InvalidValue, MissingBytes};
|
||||||
|
|
||||||
pub use lixcraft_derive::JavaSerializable;
|
pub use lixcraft_derive::JavaSerializable;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum JavaDeserError {
|
pub enum JavaDeserError {
|
||||||
@ -105,7 +106,7 @@ macro_rules! impl_wrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct VarInt(pub i32);
|
pub struct VarInt(pub i32);
|
||||||
impl_wrapper!(VarInt, i32, VarInt);
|
impl_wrapper!(VarInt, i32, VarInt);
|
||||||
|
|
||||||
@ -211,22 +212,63 @@ impl JavaSerializable for VarLong {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JavaSerializable for String {
|
impl JavaSerializable for Uuid {
|
||||||
fn size_in_bytes(&self) -> usize {
|
fn size_in_bytes(&self) -> usize {
|
||||||
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
16
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self, buf: &mut BytesMut) {
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
VarInt(self.len() as i32).serialize(buf);
|
buf.put_u128(self.as_u128())
|
||||||
buf.put_slice(self.as_bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
let len = VarInt::deserialize(buf)?;
|
Ok(Uuid::from_u128(save_get!(16, buf, get_u128)?))
|
||||||
Ok(String::from_utf8(buf.split_to(usize::from(len)).to_vec()).map_err(|_| InvalidValue)?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_string {
|
||||||
|
($i:ident, $v:expr) => {
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct $i(pub String);
|
||||||
|
impl_wrapper!($i, String, $i);
|
||||||
|
|
||||||
|
impl JavaSerializable for $i {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
VarInt(self.len() as i32).serialize(buf);
|
||||||
|
buf.put_slice(self.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
let len = VarInt::deserialize(buf)?;
|
||||||
|
if usize::from(len) > $v * 4 {
|
||||||
|
Err(InvalidValue)
|
||||||
|
} else if buf.len() < usize::from(len) {
|
||||||
|
Err(MissingBytes)
|
||||||
|
} else {
|
||||||
|
let string = String::from_utf8(buf.split_to(usize::from(len)).to_vec()).map_err(|_| InvalidValue)?;
|
||||||
|
if string.chars().count() > $v {
|
||||||
|
Err(InvalidValue)
|
||||||
|
} else {
|
||||||
|
Ok($i(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_string!(String16, 16);
|
||||||
|
impl_string!(String20, 20);
|
||||||
|
impl_string!(String255, 255);
|
||||||
|
impl_string!(String32767, 32767);
|
||||||
|
impl_string!(String262144, 262144);
|
||||||
|
|
||||||
|
impl_string!(Identifier, 32767);
|
||||||
|
|
||||||
impl<T: JavaSerializable> JavaSerializable for Vec<T> {
|
impl<T: JavaSerializable> JavaSerializable for Vec<T> {
|
||||||
fn size_in_bytes(&self) -> usize {
|
fn size_in_bytes(&self) -> usize {
|
||||||
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
VarInt(self.len() as i32).size_in_bytes() + self.len()
|
||||||
@ -249,6 +291,24 @@ impl<T: JavaSerializable> JavaSerializable for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RemainingBytes(pub Vec<u8>);
|
||||||
|
impl_wrapper!(RemainingBytes, Vec<u8>, RemainingBytes);
|
||||||
|
|
||||||
|
impl JavaSerializable for RemainingBytes {
|
||||||
|
fn size_in_bytes(&self) -> usize {
|
||||||
|
self.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
|
buf.put_slice(self.as_slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
|
Ok(RemainingBytes(buf.to_vec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NextState {
|
pub enum NextState {
|
||||||
Status,
|
Status,
|
||||||
@ -301,18 +361,18 @@ pub struct StatusResponseDescription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_json {
|
macro_rules! impl_json {
|
||||||
($t:ty) => {
|
($t:ty, $st:ident) => {
|
||||||
impl JavaSerializable for $t {
|
impl JavaSerializable for $t {
|
||||||
fn size_in_bytes(&self) -> usize {
|
fn size_in_bytes(&self) -> usize {
|
||||||
serde_json::to_string(self).unwrap().size_in_bytes()
|
$st(serde_json::to_string(self).unwrap()).size_in_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self, buf: &mut BytesMut) {
|
fn serialize(&self, buf: &mut BytesMut) {
|
||||||
serde_json::to_string(self).unwrap().serialize(buf)
|
$st(serde_json::to_string(self).unwrap()).serialize(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
fn deserialize(buf: &mut Bytes) -> Result<Self, JavaDeserError> {
|
||||||
match serde_json::from_str(&String::deserialize(buf)?) {
|
match serde_json::from_str(&$st::deserialize(buf)?) {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
Err(_) => Err(InvalidValue)
|
Err(_) => Err(InvalidValue)
|
||||||
}
|
}
|
||||||
@ -329,7 +389,7 @@ pub struct StatusResponse {
|
|||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub favicon: Option<String>
|
pub favicon: Option<String>
|
||||||
}
|
}
|
||||||
impl_json!(StatusResponse);
|
impl_json!(StatusResponse, String32767);
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
@ -431,4 +491,4 @@ pub enum Chat {
|
|||||||
selector: String //TODO ominous
|
selector: String //TODO ominous
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl_json!(Chat);
|
impl_json!(Chat, String262144);
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren