First runnable
Dieser Commit ist enthalten in:
Ursprung
00befafc33
Commit
4efe1aaf36
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
*.iml
|
*.iml
|
||||||
/.idea
|
/.idea
|
||||||
|
/Cargo.lock
|
||||||
|
365
Cargo.lock
generiert
365
Cargo.lock
generiert
@ -1,365 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "Lixcraft-Proxy"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"lixcraft-derive",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tokio",
|
|
||||||
"tokio-stream",
|
|
||||||
"tokio-util",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bytes"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-core"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-sink"
|
|
||||||
version = "0.3.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.1.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "instant"
|
|
||||||
version = "0.1.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.112"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lixcraft-derive"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
|
|
||||||
dependencies = [
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "0.7.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"miow",
|
|
||||||
"ntapi",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miow"
|
|
||||||
version = "0.3.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ntapi"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.13.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.9.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
|
||||||
dependencies = [
|
|
||||||
"instant",
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.8.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"instant",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-lite"
|
|
||||||
version = "0.2.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.36"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.2.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.136"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.79"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "1.0.85"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a684ac3dcd8913827e18cd09a68384ee66c1de24157e3c556c9ab16d85695fb7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"libc",
|
|
||||||
"memchr",
|
|
||||||
"mio",
|
|
||||||
"num_cpus",
|
|
||||||
"once_cell",
|
|
||||||
"parking_lot",
|
|
||||||
"pin-project-lite",
|
|
||||||
"signal-hook-registry",
|
|
||||||
"tokio-macros",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-macros"
|
|
||||||
version = "1.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-stream"
|
|
||||||
version = "0.1.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-util"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
"log",
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "Lixcraft-Proxy"
|
name = "lixcraft"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Lixfel <agga-games@gmx.de>"]
|
authors = ["Lixfel <agga-games@gmx.de>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -86,6 +86,6 @@ pub fn derive_serializable(input: TokenStream) -> TokenStream {
|
|||||||
},
|
},
|
||||||
Fields::Unit => impl_serializable!(struct_ident, quote! { 0 }, quote! {}, quote! { #struct_ident {} })
|
Fields::Unit => impl_serializable!(struct_ident, quote! { 0 }, quote! {}, quote! { #struct_ident {} })
|
||||||
}.into();
|
}.into();
|
||||||
println!("{}", result);
|
//println!("{}", result);
|
||||||
result
|
result
|
||||||
}
|
}
|
236
src/datatypes.rs
236
src/datatypes.rs
@ -1,236 +0,0 @@
|
|||||||
use std::fmt::{Formatter, Write};
|
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
||||||
use serde::de::{EnumAccess, Error, MapAccess, SeqAccess, Visitor};
|
|
||||||
use lixcraft_derive::Wrapper;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Wrapper)]
|
|
||||||
pub struct VarInt(pub i32);
|
|
||||||
|
|
||||||
impl From<VarInt> for usize {
|
|
||||||
fn from(v: VarInt) -> Self {
|
|
||||||
v.0 as usize
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<usize> for VarInt {
|
|
||||||
fn from(v: usize) -> Self {
|
|
||||||
VarInt(v as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for VarInt {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
|
||||||
let mut v = self.0 as u32;
|
|
||||||
let mut result = Vec::with_capacity(5);
|
|
||||||
loop {
|
|
||||||
if v & 0x80 == 0 {
|
|
||||||
result.push(v as u8);
|
|
||||||
return serializer.serialize_bytes(&result);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push((v as u8 & 0x7f) | 0x80);
|
|
||||||
v >>= 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for VarInt {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
|
||||||
let mut num_read = 0;
|
|
||||||
let mut result = 0;
|
|
||||||
loop {
|
|
||||||
let read = (&mut *deserializer).deserialize_u8(VarIntVisitor{})?;
|
|
||||||
let value = i32::from(read & 0b0111_1111);
|
|
||||||
result |= value.overflowing_shl(7 * num_read).0;
|
|
||||||
|
|
||||||
num_read += 1;
|
|
||||||
|
|
||||||
if num_read > 5 {
|
|
||||||
return Err(D::Error::custom("VarInt too large"));
|
|
||||||
}
|
|
||||||
if read & 0b1000_0000 == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(VarInt(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum NextState {
|
|
||||||
Status,
|
|
||||||
Login
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for NextState {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
|
||||||
VarInt::from(match self {
|
|
||||||
NextState::Status => 1,
|
|
||||||
NextState::Login => 2
|
|
||||||
}).serialize(serializer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for NextState {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
|
||||||
match VarInt::deserialize(deserializer)? {
|
|
||||||
VarInt(1) => Ok(NextState::Status),
|
|
||||||
VarInt(2) => Ok(NextState::Login),
|
|
||||||
_ => Err(D::Error::custom("Invalid NextState"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct StatusResponseVersion {
|
|
||||||
pub name: String,
|
|
||||||
pub protocol: i32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct StatusResponseSample {
|
|
||||||
pub name: String,
|
|
||||||
pub id: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct StatusResponsePlayers {
|
|
||||||
pub max: i32,
|
|
||||||
pub online: i32,
|
|
||||||
pub sample: Vec<StatusResponseSample>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct StatusResponseDescription {
|
|
||||||
pub text: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct StatusResponse {
|
|
||||||
pub version: StatusResponseVersion,
|
|
||||||
pub players: StatusResponsePlayers,
|
|
||||||
pub description: StatusResponseDescription,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub favicon: Option<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for StatusResponse {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
|
||||||
serializer.serialize_str(&match serde_json::to_string(self) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => return Err(serde::ser::Error::custom("Could not serialize status response"))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for StatusResponse {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
|
|
||||||
match String::deserialize(deserializer) {
|
|
||||||
Ok(json) => match serde_json::from_str(&json) {
|
|
||||||
Ok(v) => Ok(v),
|
|
||||||
Err(_) => Err(D::Error::custom("Could not parse json status response"))
|
|
||||||
},
|
|
||||||
Err(err) => Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
//TODO: Serialize, Deserialize
|
|
||||||
pub enum Font {
|
|
||||||
Uniform, //minecraft:uniform
|
|
||||||
Alt, //minecraft:alt
|
|
||||||
Default //minecraft:default
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum ClickEventAction {
|
|
||||||
open_url,
|
|
||||||
run_command,
|
|
||||||
suggest_command,
|
|
||||||
change_page,
|
|
||||||
copy_to_clipboard
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct ClickEvent {
|
|
||||||
action: ClickEventAction,
|
|
||||||
value: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub enum HoverEventAction {
|
|
||||||
show_text,
|
|
||||||
show_item,
|
|
||||||
show_entity
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct HoverEvent {
|
|
||||||
action: HoverEventAction,
|
|
||||||
value: String //or Chat (Recursion!)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct SharedChat {
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
bold: bool,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
italic: bool,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
underlined: bool,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
strikethrough: bool,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
obfuscated: bool,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
font: Font,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
color: String, //TODO Color code, format code or hex code
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
insertion: String,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
clickEvent: ClickEvent,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
hoverEvent: HoverEvent,
|
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
extra: Vec<Chat>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct Score {
|
|
||||||
name: String, //Or UUID
|
|
||||||
objective: String,
|
|
||||||
value: String
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
//TODO: Serialize, Deserialize
|
|
||||||
pub enum Chat {
|
|
||||||
StringComponent {
|
|
||||||
#[serde(flatten)]
|
|
||||||
options: SharedChat,
|
|
||||||
text: String
|
|
||||||
},
|
|
||||||
TranslationComponent {
|
|
||||||
#[serde(flatten)]
|
|
||||||
options: SharedChat,
|
|
||||||
translate: String //TODO Special strings
|
|
||||||
},
|
|
||||||
KeybindComponent {
|
|
||||||
#[serde(flatten)]
|
|
||||||
options: SharedChat,
|
|
||||||
keybind: String
|
|
||||||
},
|
|
||||||
ScoreComponent {
|
|
||||||
#[serde(flatten)]
|
|
||||||
options: SharedChat,
|
|
||||||
score: Score
|
|
||||||
},
|
|
||||||
SelectorComponent {
|
|
||||||
#[serde(flatten)]
|
|
||||||
options: SharedChat,
|
|
||||||
selector: String //TODO ominous
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,208 +0,0 @@
|
|||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use bytes::{Buf, Bytes};
|
|
||||||
use serde::de::{DeserializeSeed, Error, SeqAccess, StdError, Visitor};
|
|
||||||
use serde::{Deserialize, Deserializer};
|
|
||||||
use crate::datatypes::VarInt;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum JavaDeserError {
|
|
||||||
UnexpectedEnd,
|
|
||||||
UnexpectedCustom,
|
|
||||||
InvalidValue
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for JavaDeserError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
Debug::fmt(&self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StdError for JavaDeserError{}
|
|
||||||
|
|
||||||
impl Error for JavaDeserError{
|
|
||||||
fn custom<T>(msg: T) -> Self where T: Display {
|
|
||||||
JavaDeserError::UnexpectedCustom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct JavaDeserializer {
|
|
||||||
input: Bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JavaDeserializer {
|
|
||||||
pub fn from_bytes<'a, T: Deserialize<'a>>(data: Bytes) -> Result<T, JavaDeserError> {
|
|
||||||
let mut deserializer = JavaDeserializer{input : data };
|
|
||||||
T::deserialize(&mut deserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn assert_remaining(&self, size: usize) -> Result<(), JavaDeserError> {
|
|
||||||
match self.input.remaining() >= size {
|
|
||||||
true => Ok(()),
|
|
||||||
false => Err(JavaDeserError::UnexpectedEnd)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'de> Deserializer<'de> for &'a mut JavaDeserializer {
|
|
||||||
type Error = JavaDeserError;
|
|
||||||
|
|
||||||
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Any not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(1)?;
|
|
||||||
match self.input.get_u8() {
|
|
||||||
0x00 => visitor.visit_bool(false),
|
|
||||||
0x01 => visitor.visit_bool(true),
|
|
||||||
_ => Err(JavaDeserError::InvalidValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(1)?;
|
|
||||||
visitor.visit_i8(self.input.get_i8())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(2)?;
|
|
||||||
visitor.visit_i16(self.input.get_i16())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(4)?;
|
|
||||||
visitor.visit_i32(self.input.get_i32())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(8)?;
|
|
||||||
visitor.visit_i64(self.input.get_i64())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(1)?;
|
|
||||||
visitor.visit_u8(self.input.get_u8())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(2)?;
|
|
||||||
visitor.visit_u16(self.input.get_u16())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(4)?;
|
|
||||||
visitor.visit_u32(self.input.get_u32())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(8)?;
|
|
||||||
visitor.visit_u64(self.input.get_u64())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(4)?;
|
|
||||||
visitor.visit_f32(self.input.get_f32())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.assert_remaining(8)?;
|
|
||||||
visitor.visit_f64(self.input.get_f64())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Char not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
self.deserialize_string(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
let size = VarInt::deserialize(&mut *self)?;
|
|
||||||
if *size > 32767 {
|
|
||||||
return Err(JavaDeserError::InvalidValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.assert_remaining(usize::from(size))?;
|
|
||||||
visitor.visit_string(match String::from_utf8(self.input.copy_to_bytes(usize::from(size)).to_vec()) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => return Err(JavaDeserError::InvalidValue)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Bytes not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Byte buf not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Option not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Unit not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_unit_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Unit struct not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_newtype_struct<V>(self, name: &'static str, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
visitor.visit_newtype_struct(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
let size = VarInt::deserialize(&mut *self)?;
|
|
||||||
visitor.visit_seq(KnownLengthSeq { de: self, remaining: usize::from(size) })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
visitor.visit_seq(KnownLengthSeq { de: self, remaining: len })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_tuple_struct<V>(self, name: &'static str, len: usize, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Tuple struct not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Map not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_struct<V>(self, name: &'static str, fields: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Struct (missing #[serde(flatten)]?) not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_enum<V>(self, name: &'static str, variants: &'static [&'static str], visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Enum not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Identifier not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> where V: Visitor<'de> {
|
|
||||||
panic!("Ignored any not deserializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct KnownLengthSeq<'a> {
|
|
||||||
de: &'a mut JavaDeserializer,
|
|
||||||
remaining: usize
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de, 'a> SeqAccess<'de> for KnownLengthSeq<'a> {
|
|
||||||
type Error = <&'a mut JavaDeserializer as Deserializer<'de>>::Error;
|
|
||||||
|
|
||||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: DeserializeSeed<'de> {
|
|
||||||
match self.remaining {
|
|
||||||
0 => Ok(None),
|
|
||||||
_ => {
|
|
||||||
self.remaining -= 1;
|
|
||||||
seed.deserialize(&mut *self.de).map(Some)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
131
src/main.rs
131
src/main.rs
@ -4,8 +4,139 @@ pub mod serde;
|
|||||||
mod packets;
|
mod packets;
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::io::ErrorKind;
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||||
|
use crate::packets::handshake::HandshakePacket;
|
||||||
|
use crate::serde::{JavaSerializable, VarInt};
|
||||||
|
|
||||||
#[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");
|
||||||
|
|
||||||
|
println!("Listening on: {}", listen_addr);
|
||||||
|
|
||||||
|
let listener = TcpListener::bind(listen_addr).await?;
|
||||||
|
|
||||||
|
while let Ok((inbound, addr)) = listener.accept().await {
|
||||||
|
tokio::spawn(async move {process_initial(inbound, addr)}.await);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn process_initial(stream: TcpStream, _addr: SocketAddr) {
|
||||||
|
let mut framed = Framed::new(stream, LengthPrefixedFrame {max_length: 263});
|
||||||
|
match framed.next().await {
|
||||||
|
Some(Ok(buf)) => {
|
||||||
|
let mut buf = buf.freeze();
|
||||||
|
match VarInt::deserialize(&mut buf) {
|
||||||
|
Ok(VarInt(0)) => {
|
||||||
|
match HandshakePacket::deserialize(&mut buf) {
|
||||||
|
Ok(v) => println!("Error: {:?}", v),
|
||||||
|
Err(e) => println!("Error: {:?}", e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Ok(VarInt(v)) => println!("Error: {}", v),
|
||||||
|
Err(e) => println!("Error: {:?}", e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(Err(e)) => println!("Error: {:?}", e),
|
||||||
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
63
src/serde.rs
63
src/serde.rs
@ -4,6 +4,7 @@ use crate::serde::JavaDeserError::{InvalidValue, MissingBytes};
|
|||||||
|
|
||||||
pub use lixcraft_derive::JavaSerializable;
|
pub use lixcraft_derive::JavaSerializable;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum JavaDeserError {
|
pub enum JavaDeserError {
|
||||||
InvalidValue,
|
InvalidValue,
|
||||||
MissingBytes
|
MissingBytes
|
||||||
@ -340,12 +341,13 @@ pub enum Font {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum ClickEventAction {
|
pub enum ClickEventAction {
|
||||||
open_url,
|
OpenUrl,
|
||||||
run_command,
|
RunCommand,
|
||||||
suggest_command,
|
SuggestCommand,
|
||||||
change_page,
|
ChangePage,
|
||||||
copy_to_clipboard
|
CopyToClipboard
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
@ -355,10 +357,11 @@ pub struct ClickEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum HoverEventAction {
|
pub enum HoverEventAction {
|
||||||
show_text,
|
ShowText,
|
||||||
show_item,
|
ShowItem,
|
||||||
show_entity
|
ShowEntity
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
@ -369,28 +372,28 @@ pub struct HoverEvent {
|
|||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct SharedChat {
|
pub struct SharedChat {
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
bold: bool,
|
bold: Option<bool>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
italic: bool,
|
italic: Option<bool>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
underlined: bool,
|
underlined: Option<bool>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
strikethrough: bool,
|
strikethrough: Option<bool>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
obfuscated: bool,
|
obfuscated: Option<bool>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
font: Font,
|
font: Option<Font>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
color: String, //TODO Color code, format code or hex code
|
color: Option<String>, //TODO Color code, format code or hex code
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
insertion: String,
|
insertion: Option<String>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none", rename = "clickEvent")]
|
||||||
clickEvent: ClickEvent,
|
click_event: Option<ClickEvent>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none", rename = "hoverEvent")]
|
||||||
hoverEvent: HoverEvent,
|
hover_event: Option<HoverEvent>,
|
||||||
//#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
extra: Vec<Chat>
|
extra: Option<Vec<Chat>>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
127
src/serdemain.rs
127
src/serdemain.rs
@ -1,127 +0,0 @@
|
|||||||
extern crate core;
|
|
||||||
|
|
||||||
mod serializer;
|
|
||||||
mod datatypes;
|
|
||||||
mod deserializer;
|
|
||||||
mod packets;
|
|
||||||
mod ser;
|
|
||||||
|
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
|
||||||
use tokio_stream::StreamExt;
|
|
||||||
|
|
||||||
use std::error::Error;
|
|
||||||
use std::io::ErrorKind;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
use bytes::{Buf, BufMut, Bytes, BytesMut};
|
|
||||||
use tokio_util::codec::{Decoder, Encoder, Framed};
|
|
||||||
use crate::datatypes::VarInt;
|
|
||||||
use crate::deserializer::JavaDeserializer;
|
|
||||||
use crate::packets::handshake::HandshakePacket;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
let listen_addr = String::from("127.0.0.1:25565");
|
|
||||||
|
|
||||||
println!("Listening on: {}", listen_addr);
|
|
||||||
|
|
||||||
let listener = TcpListener::bind(listen_addr).await?;
|
|
||||||
|
|
||||||
while let Ok((inbound, addr)) = listener.accept().await {
|
|
||||||
tokio::spawn(async move {process_initial(inbound, addr)});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn process_initial(stream: TcpStream, addr: SocketAddr) {
|
|
||||||
let mut framed = Framed::new(stream, LengthPrefixedFrame {});
|
|
||||||
match framed.next().await {
|
|
||||||
Some(Ok(buf)) => {
|
|
||||||
match JavaDeserializer::from_bytes(buf.freeze()) {
|
|
||||||
Ok(v) => {
|
|
||||||
let v: HandshakePacket = v;
|
|
||||||
println!("{:?}", v);
|
|
||||||
},
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None | Some(Err(_)) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
enum VarIntReadError {
|
|
||||||
BytesMissing,
|
|
||||||
InvalidData
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LengthPrefixedFrame {}//TODO: Max expected length
|
|
||||||
|
|
||||||
impl LengthPrefixedFrame {
|
|
||||||
fn try_read_var_int(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 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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> {
|
|
||||||
match LengthPrefixedFrame::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);
|
|
||||||
Ok(Some(src.split_to(usize::from(length))))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(VarIntReadError::BytesMissing) => Ok(None),
|
|
||||||
Err(VarIntReadError::InvalidData) => 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,282 +0,0 @@
|
|||||||
use std::fmt::{Debug, Display, Formatter};
|
|
||||||
use bytes::{BufMut, BytesMut};
|
|
||||||
use serde::{Serialize, Serializer};
|
|
||||||
use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, StdError};
|
|
||||||
use crate::datatypes::VarInt;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
struct JavaSerError();
|
|
||||||
|
|
||||||
impl StdError for JavaSerError {}
|
|
||||||
|
|
||||||
impl Display for JavaSerError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
Debug::fmt(&self, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl serde::ser::Error for JavaSerError {
|
|
||||||
fn custom<T>(msg: T) -> Self where T: Display {
|
|
||||||
JavaSerError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct JavaSerializer {
|
|
||||||
output: BytesMut
|
|
||||||
}
|
|
||||||
|
|
||||||
impl JavaSerializer {
|
|
||||||
pub fn serialize<T: Serialize>(value: &T) -> BytesMut {
|
|
||||||
let mut serializer = JavaSerializer {
|
|
||||||
output: BytesMut::with_capacity(256)
|
|
||||||
};
|
|
||||||
|
|
||||||
match value.serialize(&mut serializer) {
|
|
||||||
Ok(()) => serializer.output,
|
|
||||||
Err(_) => panic!("Serialization error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Serializer for &'a mut JavaSerializer {
|
|
||||||
type Ok = ();
|
|
||||||
type Error = JavaSerError;
|
|
||||||
type SerializeSeq = Self;
|
|
||||||
type SerializeTuple = Self;
|
|
||||||
type SerializeTupleStruct = Self;
|
|
||||||
type SerializeTupleVariant = Self;
|
|
||||||
type SerializeMap = Self;
|
|
||||||
type SerializeStruct = Self;
|
|
||||||
type SerializeStructVariant = Self;
|
|
||||||
|
|
||||||
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
|
|
||||||
match v {
|
|
||||||
true => self.output.put_u8(0x00),
|
|
||||||
false => self.output.put_u8(0x01),
|
|
||||||
};
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_i8(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_i16(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_i32(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_i64(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_u8(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_u16(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_u32(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_u64(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_f32(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_f64(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Char not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
|
|
||||||
let v = v.as_bytes();
|
|
||||||
VarInt::serialize(&VarInt::from(v.len()), &mut *self)?;
|
|
||||||
self.serialize_bytes(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
|
|
||||||
self.output.put_slice(v);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error> where T: Serialize {
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Unit not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Unit struct not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_unit_variant(self, name: &'static str, variant_index: u32, variant: &'static str) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Variant not serializable in Java protocol")
|
|
||||||
//VarInt::from(variant_index as i32).serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) -> Result<Self::Ok, Self::Error> where T: Serialize {
|
|
||||||
value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_newtype_variant<T: ?Sized>(self, name: &'static str, variant_index: u32, variant: &'static str, value: &T) -> Result<Self::Ok, Self::Error> where T: Serialize {
|
|
||||||
panic!("Newtype variant not serializable in Java protocol")
|
|
||||||
//VarInt::from(variant_index as i32).serialize(self)?;
|
|
||||||
//value.serialize(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
|
|
||||||
match len {
|
|
||||||
Some(v) => VarInt::from(v).serialize(&mut *self)?,
|
|
||||||
None => ()
|
|
||||||
}
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
|
|
||||||
panic!("Tuple not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeTupleStruct, Self::Error> {
|
|
||||||
panic!("Tuple struct not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_tuple_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeTupleVariant, Self::Error> {
|
|
||||||
panic!("Tuple struct variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
|
|
||||||
panic!("Maps not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Self::Error> {
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_struct_variant(self, name: &'static str, variant_index: u32, variant: &'static str, len: usize) -> Result<Self::SerializeStructVariant, Self::Error> {
|
|
||||||
panic!("Struct variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeSeq for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeStruct for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
value.serialize(&mut **self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeTuple for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Tuple not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Tuple not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeTupleStruct for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Tuple struct not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Tuple struct not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeTupleVariant for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Tuple variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Tuple variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeMap for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Map not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Map not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Map not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> SerializeStructVariant for &'a mut JavaSerializer {
|
|
||||||
type Ok = <&'a mut JavaSerializer as Serializer>::Ok;
|
|
||||||
type Error = <&'a mut JavaSerializer as Serializer>::Error;
|
|
||||||
|
|
||||||
fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> where T: Serialize {
|
|
||||||
panic!("Struct variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn end(self) -> Result<Self::Ok, Self::Error> {
|
|
||||||
panic!("Struct variant not serializable in Java protocol")
|
|
||||||
}
|
|
||||||
}
|
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren