|
|
@ -1,38 +1,40 @@
|
|
|
|
use serde::de::Visitor;
|
|
|
|
use serde::de::Visitor;
|
|
|
|
use serde::{Deserialize, Deserializer};
|
|
|
|
use serde::{Deserialize, Deserializer};
|
|
|
|
use serde_json::Value;
|
|
|
|
use serde_json::Value;
|
|
|
|
use std::borrow::{Cow};
|
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
|
|
#[derive(Deserialize, Debug, Clone)]
|
|
|
|
pub struct BitField {
|
|
|
|
pub struct BitField {
|
|
|
|
pub name: String,
|
|
|
|
pub name: String,
|
|
|
|
pub size: i64,
|
|
|
|
pub size: i64,
|
|
|
|
pub signed: bool,
|
|
|
|
pub signed: bool,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum SwitchType {
|
|
|
|
pub enum SwitchType {
|
|
|
|
Packet(String),
|
|
|
|
Packet(String),
|
|
|
|
Type(Box<PacketDataType>),
|
|
|
|
Type(Box<PacketDataType>),
|
|
|
|
Unknown(Value),
|
|
|
|
Unknown(Value),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum TypeName {
|
|
|
|
pub enum TypeName {
|
|
|
|
Anonymous,
|
|
|
|
Anonymous,
|
|
|
|
Named(String),
|
|
|
|
Named(String),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<String> for TypeName {
|
|
|
|
|
|
|
|
fn from(value: String) -> Self {
|
|
|
|
|
|
|
|
Self::Named(value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Display for TypeName {
|
|
|
|
impl Display for TypeName {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
match self {
|
|
|
|
TypeName::Anonymous => {
|
|
|
|
TypeName::Anonymous => f.write_str("Anonymous"),
|
|
|
|
f.write_str("Anonymous")
|
|
|
|
TypeName::Named(name) => f.write_str(name.as_str()),
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeName::Named(name) => {
|
|
|
|
|
|
|
|
f.write_str(name.as_str())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -50,7 +52,8 @@ impl PartialEq<String> for TypeName {
|
|
|
|
/// These data types should be available in every version.
|
|
|
|
/// These data types should be available in every version.
|
|
|
|
/// However, they won't break anything if not present
|
|
|
|
/// However, they won't break anything if not present
|
|
|
|
/// This can also be known as the Native Types
|
|
|
|
/// This can also be known as the Native Types
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
|
|
#[non_exhaustive]
|
|
|
|
pub enum NativeType {
|
|
|
|
pub enum NativeType {
|
|
|
|
/// Please read the following link for information on parsing https://wiki.vg/Protocol#VarInt_and_VarLong
|
|
|
|
/// Please read the following link for information on parsing https://wiki.vg/Protocol#VarInt_and_VarLong
|
|
|
|
VarInt,
|
|
|
|
VarInt,
|
|
|
@ -97,40 +100,77 @@ pub enum NativeType {
|
|
|
|
OptionalNBT,
|
|
|
|
OptionalNBT,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Display for NativeType {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
|
|
|
|
|
|
let value = match self {
|
|
|
|
|
|
|
|
NativeType::Bool => "bool",
|
|
|
|
|
|
|
|
NativeType::U8 => "u8",
|
|
|
|
|
|
|
|
NativeType::U16 => "u16",
|
|
|
|
|
|
|
|
NativeType::U32 => "u32",
|
|
|
|
|
|
|
|
NativeType::U64 => "u64",
|
|
|
|
|
|
|
|
NativeType::I8 => "i8",
|
|
|
|
|
|
|
|
NativeType::I16 => "i16",
|
|
|
|
|
|
|
|
NativeType::I32 => "i32",
|
|
|
|
|
|
|
|
NativeType::I64 => "i64",
|
|
|
|
|
|
|
|
NativeType::F32 => "f32",
|
|
|
|
|
|
|
|
NativeType::F64 => "f64",
|
|
|
|
|
|
|
|
NativeType::Uuid => "uuid",
|
|
|
|
|
|
|
|
NativeType::Option(_) => "option",
|
|
|
|
|
|
|
|
NativeType::EntityMetadataLoop { .. } => "entityMetadataLoop",
|
|
|
|
|
|
|
|
NativeType::TopBitSetTerminatedArray(_) => "topbitsetterminatedarray",
|
|
|
|
|
|
|
|
NativeType::BitField(_) => "bitfield",
|
|
|
|
|
|
|
|
NativeType::Container(_) => "container",
|
|
|
|
|
|
|
|
NativeType::Switch { .. } => "switch",
|
|
|
|
|
|
|
|
NativeType::Array { .. } => "array",
|
|
|
|
|
|
|
|
NativeType::Void => "void",
|
|
|
|
|
|
|
|
NativeType::RestBuffer => "restbuffer",
|
|
|
|
|
|
|
|
NativeType::NBT => "nbt",
|
|
|
|
|
|
|
|
NativeType::OptionalNBT => "optionalnbt",
|
|
|
|
|
|
|
|
NativeType::VarInt => "varint",
|
|
|
|
|
|
|
|
NativeType::PString { .. } => "pstring",
|
|
|
|
|
|
|
|
NativeType::Buffer { .. } => "buffer",
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
write!(f, "{}", value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl NativeType {
|
|
|
|
impl NativeType {
|
|
|
|
pub fn contains_type(name: &str) -> bool {
|
|
|
|
pub fn contains_type(name: &str) -> bool {
|
|
|
|
matches!(name, "varint" | "pstring" | "buffer" | "bool" | "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64" | "f32" | "f64" | "uuid" | "option" | "entityMetadataLoop" | "topbitsetterminatedarray" | "bitfield" | "container" | "switch" | "void" | "array" | "restbuffer" | "nbt" | "optionalnbt")
|
|
|
|
matches!(
|
|
|
|
|
|
|
|
name,
|
|
|
|
|
|
|
|
"varint"
|
|
|
|
|
|
|
|
| "pstring"
|
|
|
|
|
|
|
|
| "buffer"
|
|
|
|
|
|
|
|
| "bool"
|
|
|
|
|
|
|
|
| "u8"
|
|
|
|
|
|
|
|
| "u16"
|
|
|
|
|
|
|
|
| "u32"
|
|
|
|
|
|
|
|
| "u64"
|
|
|
|
|
|
|
|
| "i8"
|
|
|
|
|
|
|
|
| "i16"
|
|
|
|
|
|
|
|
| "i32"
|
|
|
|
|
|
|
|
| "i64"
|
|
|
|
|
|
|
|
| "f32"
|
|
|
|
|
|
|
|
| "f64"
|
|
|
|
|
|
|
|
| "uuid"
|
|
|
|
|
|
|
|
| "option"
|
|
|
|
|
|
|
|
| "entityMetadataLoop"
|
|
|
|
|
|
|
|
| "topbitsetterminatedarray"
|
|
|
|
|
|
|
|
| "bitfield"
|
|
|
|
|
|
|
|
| "container"
|
|
|
|
|
|
|
|
| "switch"
|
|
|
|
|
|
|
|
| "void"
|
|
|
|
|
|
|
|
| "array"
|
|
|
|
|
|
|
|
| "restbuffer"
|
|
|
|
|
|
|
|
| "nbt"
|
|
|
|
|
|
|
|
| "optionalnbt"
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn new(name: &str, layout: Cow<'_, Value>) -> Option<Self> {
|
|
|
|
pub fn new(name: &str, layout: Cow<'_, Value>) -> Option<Self> {
|
|
|
|
match name {
|
|
|
|
match name {
|
|
|
|
"varint" => Some(NativeType::VarInt),
|
|
|
|
"varint" => Some(NativeType::VarInt),
|
|
|
|
"pstring" => {
|
|
|
|
"pstring" => Self::pstring(layout),
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
"buffer" => Self::generate_buffer(layout),
|
|
|
|
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
|
|
|
|
|
|
|
|
if let Some(count_type) =
|
|
|
|
|
|
|
|
NativeType::new(&count_type, Cow::Owned(Value::Null)) {
|
|
|
|
|
|
|
|
return Some(NativeType::PString {
|
|
|
|
|
|
|
|
count_type: Box::new(count_type),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"buffer" => {
|
|
|
|
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
|
|
|
|
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
|
|
|
|
|
|
|
|
if let Some(count_type) =
|
|
|
|
|
|
|
|
NativeType::new(&count_type, Cow::Owned(Value::Null))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return Some(NativeType::PString {
|
|
|
|
|
|
|
|
count_type: Box::new(count_type),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
"bool" => Some(NativeType::Bool),
|
|
|
|
"bool" => Some(NativeType::Bool),
|
|
|
|
"u8" => Some(NativeType::U8),
|
|
|
|
"u8" => Some(NativeType::U8),
|
|
|
|
"u16" => Some(NativeType::U16),
|
|
|
|
"u16" => Some(NativeType::U16),
|
|
|
@ -144,24 +184,36 @@ impl NativeType {
|
|
|
|
"f64" => Some(NativeType::F64),
|
|
|
|
"f64" => Some(NativeType::F64),
|
|
|
|
"uuid" => Some(NativeType::Uuid),
|
|
|
|
"uuid" => Some(NativeType::Uuid),
|
|
|
|
"option" => Some(NativeType::Option(build_inner_type(layout.into_owned()))),
|
|
|
|
"option" => Some(NativeType::Option(build_inner_type(layout.into_owned()))),
|
|
|
|
"entityMetadataLoop" => {
|
|
|
|
"entityMetadataLoop" => Self::entity_metadata_loop(layout),
|
|
|
|
match layout.into_owned() {
|
|
|
|
"topbitsetterminatedarray" => Self::top_bitsetterminated_array(layout),
|
|
|
|
Value::Object(mut layout) => {
|
|
|
|
"bitfield" => Self::bitfield(layout),
|
|
|
|
let end_val = layout
|
|
|
|
"container" => Self::container(layout),
|
|
|
|
.remove("endVal")
|
|
|
|
|
|
|
|
.and_then(|v| v.as_i64())
|
|
|
|
"switch" => Self::switch(layout),
|
|
|
|
.unwrap_or_default();
|
|
|
|
"void" => Some(NativeType::Void),
|
|
|
|
let inner_type = layout.remove("type").unwrap_or_default();
|
|
|
|
"array" => Self::array(layout),
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
Some(NativeType::EntityMetadataLoop {
|
|
|
|
"restbuffer" => Some(NativeType::RestBuffer),
|
|
|
|
end_val,
|
|
|
|
"nbt" => Some(NativeType::NBT),
|
|
|
|
metadata_type: inner_type,
|
|
|
|
"optionalnbt" => Some(NativeType::OptionalNBT),
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => None,
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"topbitsetterminatedarray" => {
|
|
|
|
|
|
|
|
|
|
|
|
pub fn pstring(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
|
|
|
|
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
|
|
|
|
|
|
|
|
if let Some(count_type) = NativeType::new(&count_type, Cow::Owned(Value::Null)) {
|
|
|
|
|
|
|
|
return Some(NativeType::PString {
|
|
|
|
|
|
|
|
count_type: Box::new(count_type),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn top_bitsetterminated_array(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
if let Value::Object(mut layout) = layout.into_owned() {
|
|
|
|
if let Value::Object(mut layout) = layout.into_owned() {
|
|
|
|
let inner_type = layout.remove("type").unwrap_or_default();
|
|
|
|
let inner_type = layout.remove("type").unwrap_or_default();
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
@ -169,7 +221,8 @@ impl NativeType {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"bitfield" => {
|
|
|
|
|
|
|
|
|
|
|
|
pub fn bitfield(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
if let Value::Array(bit_fields) = layout.into_owned() {
|
|
|
|
if let Value::Array(bit_fields) = layout.into_owned() {
|
|
|
|
let bit_fields_vec = bit_fields
|
|
|
|
let bit_fields_vec = bit_fields
|
|
|
|
.into_iter()
|
|
|
|
.into_iter()
|
|
|
@ -181,38 +234,16 @@ impl NativeType {
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"container" => {
|
|
|
|
|
|
|
|
if let Value::Array(containers) = layout.into_owned() {
|
|
|
|
|
|
|
|
let containers_vec = containers
|
|
|
|
|
|
|
|
.into_iter()
|
|
|
|
|
|
|
|
.map(|v| {
|
|
|
|
|
|
|
|
if let Value::Object(mut obj) = v {
|
|
|
|
|
|
|
|
if let Some(name) = obj.remove("name") {
|
|
|
|
|
|
|
|
let name = name.as_str().unwrap().to_string();
|
|
|
|
|
|
|
|
let inner_type = obj.remove("type").unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
(TypeName::Named(name), inner_type)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
let inner_type = obj.remove("type").unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
(TypeName::Anonymous, inner_type)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
panic!("Container is not an object");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some(NativeType::Container(containers_vec))
|
|
|
|
pub fn switch(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"switch" => {
|
|
|
|
|
|
|
|
if let Value::Object(mut layout) = layout.into_owned() {
|
|
|
|
if let Value::Object(mut layout) = layout.into_owned() {
|
|
|
|
return Some(NativeType::Switch {
|
|
|
|
return Some(NativeType::Switch {
|
|
|
|
compare_to: layout.remove("compareTo").unwrap().as_str().unwrap_or_default().to_string(),
|
|
|
|
compare_to: layout
|
|
|
|
|
|
|
|
.remove("compareTo")
|
|
|
|
|
|
|
|
.unwrap()
|
|
|
|
|
|
|
|
.as_str()
|
|
|
|
|
|
|
|
.unwrap_or_default()
|
|
|
|
|
|
|
|
.to_string(),
|
|
|
|
fields: layout
|
|
|
|
fields: layout
|
|
|
|
.remove("fields")
|
|
|
|
.remove("fields")
|
|
|
|
.and_then(|v| {
|
|
|
|
.and_then(|v| {
|
|
|
@ -225,10 +256,20 @@ impl NativeType {
|
|
|
|
if value.starts_with("packet") {
|
|
|
|
if value.starts_with("packet") {
|
|
|
|
(k, SwitchType::Packet(value))
|
|
|
|
(k, SwitchType::Packet(value))
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
(k, SwitchType::Type(build_inner_type(Value::String(value))))
|
|
|
|
(
|
|
|
|
|
|
|
|
k,
|
|
|
|
|
|
|
|
SwitchType::Type(build_inner_type(
|
|
|
|
|
|
|
|
Value::String(value),
|
|
|
|
|
|
|
|
)),
|
|
|
|
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if let Value::Array(array) = v {
|
|
|
|
} else if let Value::Array(array) = v {
|
|
|
|
(k, SwitchType::Type(build_inner_type(Value::Array(array))))
|
|
|
|
(
|
|
|
|
|
|
|
|
k,
|
|
|
|
|
|
|
|
SwitchType::Type(build_inner_type(Value::Array(
|
|
|
|
|
|
|
|
array,
|
|
|
|
|
|
|
|
))),
|
|
|
|
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
(k, SwitchType::Unknown(v))
|
|
|
|
(k, SwitchType::Unknown(v))
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -240,13 +281,15 @@ impl NativeType {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.unwrap_or_default(),
|
|
|
|
.unwrap_or_default(),
|
|
|
|
default: layout.remove("default").map(|v| v.as_str().unwrap_or_default().to_string()),
|
|
|
|
default: layout
|
|
|
|
|
|
|
|
.remove("default")
|
|
|
|
|
|
|
|
.map(|v| v.as_str().unwrap_or_default().to_string()),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"void" => Some(NativeType::Void),
|
|
|
|
|
|
|
|
"array" => {
|
|
|
|
pub fn array(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
let value = NativeType::new(
|
|
|
|
let value = NativeType::new(
|
|
|
|
obj.remove("countType")
|
|
|
|
obj.remove("countType")
|
|
|
@ -266,42 +309,64 @@ impl NativeType {
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
"restbuffer" => Some(NativeType::RestBuffer),
|
|
|
|
pub fn container(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
"nbt" => Some(NativeType::NBT),
|
|
|
|
if let Value::Array(containers) = layout.into_owned() {
|
|
|
|
"optionalnbt" => Some(NativeType::OptionalNBT),
|
|
|
|
let containers_vec = containers
|
|
|
|
|
|
|
|
.into_iter()
|
|
|
|
|
|
|
|
.map(|v| {
|
|
|
|
|
|
|
|
if let Value::Object(mut obj) = v {
|
|
|
|
|
|
|
|
if let Some(name) = obj.remove("name") {
|
|
|
|
|
|
|
|
let name = name.as_str().unwrap().to_string();
|
|
|
|
|
|
|
|
let inner_type = obj.remove("type").unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
(TypeName::Named(name), inner_type)
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
let inner_type = obj.remove("type").unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
(TypeName::Anonymous, inner_type)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
panic!("Container is not an object");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Some(NativeType::Container(containers_vec))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn entity_metadata_loop(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
|
|
|
|
match layout.into_owned() {
|
|
|
|
|
|
|
|
Value::Object(mut layout) => {
|
|
|
|
|
|
|
|
let end_val = layout
|
|
|
|
|
|
|
|
.remove("endVal")
|
|
|
|
|
|
|
|
.and_then(|v| v.as_i64())
|
|
|
|
|
|
|
|
.unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = layout.remove("type").unwrap_or_default();
|
|
|
|
|
|
|
|
let inner_type = build_inner_type(inner_type);
|
|
|
|
|
|
|
|
Some(NativeType::EntityMetadataLoop {
|
|
|
|
|
|
|
|
end_val,
|
|
|
|
|
|
|
|
metadata_type: inner_type,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn get_name(&self) -> &str {
|
|
|
|
|
|
|
|
match self {
|
|
|
|
pub fn generate_buffer(layout: Cow<Value>) -> Option<NativeType> {
|
|
|
|
NativeType::Bool => "bool",
|
|
|
|
if let Value::Object(mut obj) = layout.into_owned() {
|
|
|
|
NativeType::U8 => "u8",
|
|
|
|
if let Value::String(count_type) = obj.remove("countType").unwrap_or_default() {
|
|
|
|
NativeType::U16 => "u16",
|
|
|
|
if let Some(count_type) = NativeType::new(&count_type, Cow::Owned(Value::Null)) {
|
|
|
|
NativeType::U32 => "u32",
|
|
|
|
return Some(NativeType::PString {
|
|
|
|
NativeType::U64 => "u64",
|
|
|
|
count_type: Box::new(count_type),
|
|
|
|
NativeType::I8 => "i8",
|
|
|
|
});
|
|
|
|
NativeType::I16 => "i16",
|
|
|
|
}
|
|
|
|
NativeType::I32 => "i32",
|
|
|
|
|
|
|
|
NativeType::I64 => "i64",
|
|
|
|
|
|
|
|
NativeType::F32 => "f32",
|
|
|
|
|
|
|
|
NativeType::F64 => "f64",
|
|
|
|
|
|
|
|
NativeType::Uuid => "uuid",
|
|
|
|
|
|
|
|
NativeType::Option(_) => "option",
|
|
|
|
|
|
|
|
NativeType::EntityMetadataLoop { .. } => "entityMetadataLoop",
|
|
|
|
|
|
|
|
NativeType::TopBitSetTerminatedArray(_) => "topbitsetterminatedarray",
|
|
|
|
|
|
|
|
NativeType::BitField(_) => "bitfield",
|
|
|
|
|
|
|
|
NativeType::Container(_) => "container",
|
|
|
|
|
|
|
|
NativeType::Switch { .. } => "switch",
|
|
|
|
|
|
|
|
NativeType::Array { .. } => "array",
|
|
|
|
|
|
|
|
NativeType::Void => "void",
|
|
|
|
|
|
|
|
NativeType::RestBuffer => "restbuffer",
|
|
|
|
|
|
|
|
NativeType::NBT => "nbt",
|
|
|
|
|
|
|
|
NativeType::OptionalNBT => "optionalnbt",
|
|
|
|
|
|
|
|
NativeType::VarInt => { "varint" }
|
|
|
|
|
|
|
|
NativeType::PString { .. } => { "pstring" }
|
|
|
|
|
|
|
|
NativeType::Buffer { .. } => { "buffer" }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
#[inline]
|
|
|
@ -313,40 +378,49 @@ fn build_inner_type(value: Value) -> Box<PacketDataType> {
|
|
|
|
Box::new(PacketDataType::Native(simple_type))
|
|
|
|
Box::new(PacketDataType::Native(simple_type))
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Probably a reference to a built type
|
|
|
|
// Probably a reference to a built type
|
|
|
|
Box::new(PacketDataType::Other(simple_type, Value::Null))
|
|
|
|
Box::new(PacketDataType::Other {
|
|
|
|
|
|
|
|
name: Some(simple_type.into()),
|
|
|
|
|
|
|
|
value: Value::Null,
|
|
|
|
|
|
|
|
})
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Value::Array(mut array) => {
|
|
|
|
Value::Array(mut array) => {
|
|
|
|
if array.len() != 2 {
|
|
|
|
if array.len() != 2 {
|
|
|
|
return Box::new(PacketDataType::Other(String::new(), Value::Array(array)));
|
|
|
|
return Box::new(PacketDataType::Other {
|
|
|
|
|
|
|
|
name: None,
|
|
|
|
|
|
|
|
value: Value::Array(array),
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let inner_value = Cow::Owned(array.pop().unwrap_or_default());
|
|
|
|
let inner_value = Cow::Owned(array.pop().unwrap_or_default());
|
|
|
|
let key = array.pop().unwrap();
|
|
|
|
let key = array.pop().unwrap();
|
|
|
|
if let Value::String(key) = &key {
|
|
|
|
if let Value::String(key) = key {
|
|
|
|
let value = PacketDataType::new(key, Cow::clone(&inner_value)).or_else(|| {
|
|
|
|
let value = PacketDataType::new(&key, Cow::clone(&inner_value)).or_else(|| {
|
|
|
|
let option = NativeType::new(key, inner_value.clone());
|
|
|
|
let option = NativeType::new(&key, inner_value.clone());
|
|
|
|
option.map(PacketDataType::Native)
|
|
|
|
option.map(PacketDataType::Native)
|
|
|
|
});
|
|
|
|
});
|
|
|
|
if let Some(value) = value {
|
|
|
|
if let Some(value) = value {
|
|
|
|
Box::new(value)
|
|
|
|
Box::new(value)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Box::new(PacketDataType::Other(
|
|
|
|
Box::new(PacketDataType::Other {
|
|
|
|
key.clone(),
|
|
|
|
name: Some(key.into()),
|
|
|
|
inner_value.into_owned(),
|
|
|
|
value: inner_value.into_owned(),
|
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Box::new(PacketDataType::Other(
|
|
|
|
Box::new(PacketDataType::Other {
|
|
|
|
key.as_str().unwrap_or_default().to_string(),
|
|
|
|
name: None,
|
|
|
|
inner_value.into_owned(),
|
|
|
|
value: inner_value.into_owned(),
|
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
v => Box::new(PacketDataType::Other(String::new(), v)),
|
|
|
|
v => Box::new(PacketDataType::Other {
|
|
|
|
|
|
|
|
name: None,
|
|
|
|
|
|
|
|
value: v,
|
|
|
|
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum PacketDataType {
|
|
|
|
pub enum PacketDataType {
|
|
|
|
// Just a pure native type
|
|
|
|
// Just a pure native type
|
|
|
|
Native(NativeType),
|
|
|
|
Native(NativeType),
|
|
|
@ -359,8 +433,20 @@ pub enum PacketDataType {
|
|
|
|
// The value of the built type
|
|
|
|
// The value of the built type
|
|
|
|
value: NativeType,
|
|
|
|
value: NativeType,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
/// A Type that could not be built or parsed. This is a fallback for when we don't know what the type is
|
|
|
|
|
|
|
|
/// This type is usually a reference to a built type
|
|
|
|
|
|
|
|
Other {
|
|
|
|
|
|
|
|
// The name of the type if found
|
|
|
|
|
|
|
|
name: Option<TypeName>,
|
|
|
|
|
|
|
|
// The JSON value of the type
|
|
|
|
|
|
|
|
value: Value,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Other(String, Value),
|
|
|
|
impl From<NativeType> for PacketDataType {
|
|
|
|
|
|
|
|
fn from(native: NativeType) -> Self {
|
|
|
|
|
|
|
|
PacketDataType::Native(native)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl PacketDataType {
|
|
|
|
impl PacketDataType {
|
|
|
@ -370,7 +456,10 @@ impl PacketDataType {
|
|
|
|
Value::String(string) => Some(PacketDataType::UnknownNativeType(string)),
|
|
|
|
Value::String(string) => Some(PacketDataType::UnknownNativeType(string)),
|
|
|
|
Value::Array(mut array) => {
|
|
|
|
Value::Array(mut array) => {
|
|
|
|
if array.len() != 2 {
|
|
|
|
if array.len() != 2 {
|
|
|
|
return Some(PacketDataType::Other(key.to_string(), Value::Array(array)));
|
|
|
|
return Some(PacketDataType::Other {
|
|
|
|
|
|
|
|
name: None,
|
|
|
|
|
|
|
|
value: Value::Array(array),
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let inner_type_values = array.pop().unwrap_or_default();
|
|
|
|
let inner_type_values = array.pop().unwrap_or_default();
|
|
|
@ -384,14 +473,18 @@ impl PacketDataType {
|
|
|
|
value: type_,
|
|
|
|
value: type_,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Some(PacketDataType::Other(inner_type_name, inner_type_values))
|
|
|
|
Some(PacketDataType::Other {
|
|
|
|
|
|
|
|
name: Some(inner_type_name.into()),
|
|
|
|
|
|
|
|
value: inner_type_values,
|
|
|
|
|
|
|
|
})
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
v => {
|
|
|
|
v => Some(PacketDataType::Other {
|
|
|
|
Some(PacketDataType::Other(key.to_string(), v))
|
|
|
|
name: None,
|
|
|
|
}
|
|
|
|
value: v,
|
|
|
|
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
None
|
|
|
@ -407,7 +500,7 @@ pub struct PacketDataTypes {
|
|
|
|
use std::fmt;
|
|
|
|
use std::fmt;
|
|
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
|
|
|
|
|
|
|
|
|
|
use serde::de::{MapAccess};
|
|
|
|
use serde::de::MapAccess;
|
|
|
|
|
|
|
|
|
|
|
|
impl<'de> Deserialize<'de> for PacketDataTypes {
|
|
|
|
impl<'de> Deserialize<'de> for PacketDataTypes {
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
|
@ -419,7 +512,7 @@ impl<'de> Deserialize<'de> for PacketDataTypes {
|
|
|
|
impl<'de> Visitor<'de> for PacketDataTypesVisitor {
|
|
|
|
impl<'de> Visitor<'de> for PacketDataTypesVisitor {
|
|
|
|
type Value = PacketDataTypes;
|
|
|
|
type Value = PacketDataTypes;
|
|
|
|
|
|
|
|
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
|
|
|
formatter.write_str("struct PacketDataTypes")
|
|
|
|
formatter.write_str("struct PacketDataTypes")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|