use std::ops::{Deref, DerefMut}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::de::Error; use lixcraft_derive::Wrapper; #[derive(Copy, Clone, Debug, PartialEq, Eq, Wrapper)] pub struct VarInt(pub i32); impl From for usize { fn from(v: VarInt) -> Self { v.0 as usize } } impl From for VarInt { fn from(v: usize) -> Self { VarInt(v as i32) } } impl Serialize for VarInt { fn serialize(&self, serializer: S) -> Result where S: Serializer { let mut v = self.0 as u32; loop { if v & 0x80 == 0 { return serializer.serialize_u8(v as u8); } serializer.serialize_u8((v as u8 & 0x7f) | 0x80)?; v >>= 7; } } } impl<'de> Deserialize<'de> for VarInt { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { let mut num_read = 0; let mut result = 0; loop { let read = u8::deserialize(deserializer)?; 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(&self, serializer: S) -> Result where S: Serializer { VarInt::from(match self { NextState::Status => 1, NextState::Login => 2 }).serialize(serializer) } } impl<'de> Deserialize<'de> for NextState { fn deserialize(deserializer: D) -> Result 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 { name: String, protocol: i32 } #[derive(Debug, Serialize, Deserialize)] pub struct StatusResponseSample { name: String, id: String } #[derive(Debug, Serialize, Deserialize)] pub struct StatusResponsePlayers { max: i32, online: i32, sample: Vec } #[derive(Debug, Serialize, Deserialize)] pub struct StatusResponseDescription { text: String } #[derive(Debug)] pub struct StatusResponse { version: StatusResponseVersion, players: StatusResponsePlayers, description: StatusResponseDescription, //#[serde(skip_serializing_if = "Option::is_none")] favicon: Option } impl Serialize for StatusResponse { fn serialize(&self, serializer: S) -> Result 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(deserializer: D) -> Result 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) } } }