Less heap allocations
This commit is contained in:
parent
bab92b39ca
commit
bd8bac1ff5
@ -100,7 +100,7 @@ impl serde::Serialize for TextComponent<'_> {
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(self.encode().as_slice())
|
||||
serializer.serialize_bytes(&self.encode())
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ impl<'a> TextComponent<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn encode(&self) -> Vec<u8> {
|
||||
pub fn encode(&self) -> bytes::BytesMut {
|
||||
// TODO: Somehow fix this ugly mess
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -215,9 +215,7 @@ impl<'a> TextComponent<'a> {
|
||||
// dbg!(pumpkin_nbt::serializer::to_bytes_unnamed(&astruct).unwrap().to_vec());
|
||||
|
||||
// TODO
|
||||
pumpkin_nbt::serializer::to_bytes_unnamed(&astruct)
|
||||
.unwrap()
|
||||
.to_vec()
|
||||
pumpkin_nbt::serializer::to_bytes_unnamed(&astruct).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ impl ClientPacket for CBossEvent<'_> {
|
||||
flags,
|
||||
} => {
|
||||
bytebuf.put_var_int(&VarInt::from(0u8));
|
||||
bytebuf.put_slice(title.encode().as_slice());
|
||||
bytebuf.put_slice(&title.encode());
|
||||
bytebuf.put_f32(*health);
|
||||
bytebuf.put_var_int(color);
|
||||
bytebuf.put_var_int(division);
|
||||
@ -43,7 +43,7 @@ impl ClientPacket for CBossEvent<'_> {
|
||||
}
|
||||
BosseventAction::UpdateTile(title) => {
|
||||
bytebuf.put_var_int(&VarInt::from(3u8));
|
||||
bytebuf.put_slice(title.encode().as_slice());
|
||||
bytebuf.put_slice(&title.encode());
|
||||
}
|
||||
BosseventAction::UpdateStyle { color, dividers } => {
|
||||
bytebuf.put_var_int(&VarInt::from(4u8));
|
||||
|
||||
@ -36,11 +36,12 @@ impl PacketDecoder {
|
||||
pub fn decode(&mut self) -> Result<Option<RawPacket>, PacketDecodeError> {
|
||||
let mut r = &self.buf[..];
|
||||
|
||||
let packet_len = match VarInt::decode_partial(&mut r) {
|
||||
let packet_len = match VarInt::decode(&mut r) {
|
||||
Ok(len) => len,
|
||||
Err(VarIntDecodeError::Incomplete) => return Ok(None),
|
||||
Err(VarIntDecodeError::TooLarge) => Err(PacketDecodeError::MalformedLength)?,
|
||||
};
|
||||
let packet_len = packet_len.0;
|
||||
|
||||
if !(0..=MAX_PACKET_SIZE).contains(&packet_len) {
|
||||
Err(PacketDecodeError::OutOfBounds)?
|
||||
@ -222,11 +223,9 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Helper function to encrypt data using AES-128 CFB-8 mode
|
||||
fn encrypt_aes128(data: &[u8], key: &[u8; 16], iv: &[u8; 16]) -> Vec<u8> {
|
||||
fn encrypt_aes128(mut data: &mut [u8], key: &[u8; 16], iv: &[u8; 16]) {
|
||||
let encryptor = Cfb8Encryptor::<Aes128>::new_from_slices(key, iv).expect("Invalid key/iv");
|
||||
let mut encrypted = data.to_vec();
|
||||
encryptor.encrypt(&mut encrypted);
|
||||
encrypted
|
||||
encryptor.encrypt(&mut data);
|
||||
}
|
||||
|
||||
/// Helper function to build a packet with optional compression and encryption
|
||||
@ -274,7 +273,8 @@ mod tests {
|
||||
|
||||
// Encrypt if key and iv are provided
|
||||
if let (Some(k), Some(v)) = (key, iv) {
|
||||
encrypt_aes128(&packet, k, v)
|
||||
encrypt_aes128(&mut packet, k, v);
|
||||
packet
|
||||
} else {
|
||||
packet
|
||||
}
|
||||
@ -416,7 +416,7 @@ mod tests {
|
||||
packet_buffer.put_var_int(&packet_len_varint);
|
||||
packet_buffer.put_slice(buffer.buf());
|
||||
|
||||
let packet_bytes = packet_buffer.buf().to_vec();
|
||||
let packet_bytes = packet_buffer.buf();
|
||||
|
||||
// Initialize the decoder with compression enabled
|
||||
let mut decoder = PacketDecoder::default();
|
||||
|
||||
@ -37,11 +37,11 @@ impl Default for PacketEncoder {
|
||||
impl PacketEncoder {
|
||||
pub fn append_packet<P: ClientPacket>(&mut self, packet: &P) -> Result<(), PacketEncodeError> {
|
||||
let start_len = self.buf.len();
|
||||
|
||||
let mut packet_buf = ByteBuffer::empty();
|
||||
// Write the Packet ID first
|
||||
VarInt(P::PACKET_ID).encode(&mut self.buf);
|
||||
let mut packet_buf = ByteBuffer::empty();
|
||||
// Now write the packet into an empty buffer
|
||||
packet.write(&mut packet_buf);
|
||||
|
||||
self.buf.put(packet_buf.buf());
|
||||
|
||||
let data_len = self.buf.len() - start_len;
|
||||
@ -229,11 +229,9 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Helper function to decrypt data using AES-128 CFB-8 mode
|
||||
fn decrypt_aes128(encrypted_data: &[u8], key: &[u8; 16], iv: &[u8; 16]) -> Vec<u8> {
|
||||
fn decrypt_aes128(mut encrypted_data: &mut [u8], key: &[u8; 16], iv: &[u8; 16]) {
|
||||
let decryptor = Cfb8Decryptor::<Aes128>::new_from_slices(key, iv).expect("Invalid key/iv");
|
||||
let mut decrypted = encrypted_data.to_vec();
|
||||
decryptor.decrypt(&mut decrypted);
|
||||
decrypted
|
||||
decryptor.decrypt(&mut encrypted_data);
|
||||
}
|
||||
|
||||
/// Helper function to build a packet with optional compression and encryption
|
||||
@ -356,13 +354,13 @@ mod tests {
|
||||
let key = [0x00u8; 16]; // Example key
|
||||
|
||||
// Build the packet with encryption enabled (no compression)
|
||||
let packet_bytes = build_packet_with_encoder(&packet, None, Some(&key));
|
||||
let mut packet_bytes = build_packet_with_encoder(&packet, None, Some(&key));
|
||||
|
||||
// Decrypt the packet
|
||||
let decrypted_packet = decrypt_aes128(&packet_bytes, &key, &key);
|
||||
decrypt_aes128(&mut packet_bytes, &key, &key);
|
||||
|
||||
// Decode the packet manually to verify correctness
|
||||
let mut buffer = &decrypted_packet[..];
|
||||
let mut buffer = &packet_bytes[..];
|
||||
|
||||
// Read packet length VarInt
|
||||
let packet_length = decode_varint(&mut buffer).expect("Failed to decode packet length");
|
||||
@ -399,13 +397,14 @@ mod tests {
|
||||
let key = [0x01u8; 16]; // Example key
|
||||
|
||||
// Build the packet with both compression and encryption enabled
|
||||
let packet_bytes = build_packet_with_encoder(&packet, Some(compression_info), Some(&key));
|
||||
let mut packet_bytes =
|
||||
build_packet_with_encoder(&packet, Some(compression_info), Some(&key));
|
||||
|
||||
// Decrypt the packet
|
||||
let decrypted_packet = decrypt_aes128(&packet_bytes, &key, &key);
|
||||
decrypt_aes128(&mut packet_bytes, &key, &key);
|
||||
|
||||
// Decode the packet manually to verify correctness
|
||||
let mut buffer = &decrypted_packet[..];
|
||||
let mut buffer = &packet_bytes[..];
|
||||
|
||||
// Read packet length VarInt
|
||||
let packet_length = decode_varint(&mut buffer).expect("Failed to decode packet length");
|
||||
|
||||
@ -11,7 +11,7 @@ pub struct SCookieResponse {
|
||||
pub key: Identifier,
|
||||
pub has_payload: bool,
|
||||
pub payload_length: Option<VarInt>,
|
||||
pub payload: Option<Vec<u8>>, // 5120,
|
||||
pub payload: Option<bytes::Bytes>, // 5120,
|
||||
}
|
||||
|
||||
const MAX_PAYLOAD_SIZE: i32 = 5120;
|
||||
@ -39,7 +39,7 @@ impl ServerPacket for SCookieResponse {
|
||||
));
|
||||
}
|
||||
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?.to_vec();
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?;
|
||||
|
||||
Ok(Self {
|
||||
key,
|
||||
|
||||
@ -8,14 +8,14 @@ use crate::{
|
||||
#[server_packet("config:custom_payload")]
|
||||
pub struct SPluginMessage {
|
||||
pub channel: Identifier,
|
||||
pub data: Vec<u8>,
|
||||
pub data: bytes::BytesMut,
|
||||
}
|
||||
|
||||
impl ServerPacket for SPluginMessage {
|
||||
fn read(bytebuf: &mut ByteBuffer) -> Result<Self, DeserializerError> {
|
||||
Ok(Self {
|
||||
channel: bytebuf.get_string()?,
|
||||
data: bytebuf.get_slice().to_vec(),
|
||||
data: bytebuf.get_slice(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ pub struct SCookieResponse {
|
||||
pub key: Identifier,
|
||||
pub has_payload: bool,
|
||||
pub payload_length: Option<VarInt>,
|
||||
pub payload: Option<Vec<u8>>, // 5120,
|
||||
pub payload: Option<bytes::Bytes>, // 5120,
|
||||
}
|
||||
|
||||
const MAX_PAYLOAD_SIZE: i32 = 5120;
|
||||
@ -38,7 +38,7 @@ impl ServerPacket for SCookieResponse {
|
||||
));
|
||||
}
|
||||
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?.to_vec();
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?;
|
||||
|
||||
Ok(Self {
|
||||
key,
|
||||
|
||||
@ -8,9 +8,9 @@ use crate::{
|
||||
#[server_packet("login:key")]
|
||||
pub struct SEncryptionResponse {
|
||||
pub shared_secret_length: VarInt,
|
||||
pub shared_secret: Vec<u8>,
|
||||
pub shared_secret: bytes::Bytes,
|
||||
pub verify_token_length: VarInt,
|
||||
pub verify_token: Vec<u8>,
|
||||
pub verify_token: bytes::Bytes,
|
||||
}
|
||||
|
||||
impl ServerPacket for SEncryptionResponse {
|
||||
@ -21,9 +21,9 @@ impl ServerPacket for SEncryptionResponse {
|
||||
let verify_token = bytebuf.copy_to_bytes(shared_secret_length.0 as usize)?;
|
||||
Ok(Self {
|
||||
shared_secret_length,
|
||||
shared_secret: shared_secret.to_vec(),
|
||||
shared_secret,
|
||||
verify_token_length,
|
||||
verify_token: verify_token.to_vec(),
|
||||
verify_token,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ pub struct SCookieResponse {
|
||||
pub key: Identifier,
|
||||
pub has_payload: bool,
|
||||
pub payload_length: Option<VarInt>,
|
||||
pub payload: Option<Vec<u8>>, // 5120,
|
||||
pub payload: Option<bytes::Bytes>, // 5120,
|
||||
}
|
||||
|
||||
const MAX_PAYLOAD_SIZE: i32 = 5120;
|
||||
@ -38,7 +38,7 @@ impl ServerPacket for SCookieResponse {
|
||||
));
|
||||
}
|
||||
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?.to_vec();
|
||||
let payload = bytebuf.copy_to_bytes(length as usize)?;
|
||||
|
||||
Ok(Self {
|
||||
key,
|
||||
|
||||
@ -7,8 +7,7 @@ use crate::VarIntType;
|
||||
pub struct VarInt(pub VarIntType);
|
||||
|
||||
impl VarInt {
|
||||
/// The maximum number of bytes a `VarInt` could occupy when read from and
|
||||
/// written to the Minecraft protocol.
|
||||
/// The maximum number of bytes a `VarInt`
|
||||
pub const MAX_SIZE: usize = 5;
|
||||
|
||||
/// Returns the exact number of bytes this varint will write when
|
||||
@ -20,30 +19,12 @@ impl VarInt {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_partial(r: &mut impl Buf) -> Result<i32, VarIntDecodeError> {
|
||||
let mut val = 0;
|
||||
for i in 0..Self::MAX_SIZE {
|
||||
if !r.has_remaining() {
|
||||
return Err(VarIntDecodeError::Incomplete);
|
||||
}
|
||||
let byte = r.get_u8();
|
||||
val |= (i32::from(byte) & 0b01111111) << (i * 7);
|
||||
if byte & 0b10000000 == 0 {
|
||||
return Ok(val);
|
||||
}
|
||||
}
|
||||
Err(VarIntDecodeError::TooLarge)
|
||||
}
|
||||
|
||||
pub fn encode(&self, w: &mut impl BufMut) {
|
||||
let mut val = self.0;
|
||||
for _ in 0..Self::MAX_SIZE {
|
||||
let mut b: u8 = val as u8 & 0b01111111;
|
||||
let b: u8 = val as u8 & 0b01111111;
|
||||
val >>= 7;
|
||||
if val != 0 {
|
||||
b |= 0b10000000;
|
||||
}
|
||||
w.put_u8(b);
|
||||
w.put_u8(if val == 0 { b } else { b | 0b10000000 });
|
||||
if val == 0 {
|
||||
break;
|
||||
}
|
||||
@ -57,8 +38,8 @@ impl VarInt {
|
||||
return Err(VarIntDecodeError::Incomplete);
|
||||
}
|
||||
let byte = r.get_u8();
|
||||
val |= (i32::from(byte) & 0b01111111) << (i * 7);
|
||||
if byte & 0b10000000 == 0 {
|
||||
val |= (i32::from(byte) & 0x7F) << (i * 7);
|
||||
if byte & 0x80 == 0 {
|
||||
return Ok(VarInt(val));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,10 @@ use crate::VarLongType;
|
||||
pub struct VarLong(pub VarLongType);
|
||||
|
||||
impl VarLong {
|
||||
/// The maximum number of bytes a `VarInt` could occupy when read from and
|
||||
/// written to the Minecraft protocol.
|
||||
/// The maximum number of bytes a `VarLong`
|
||||
pub const MAX_SIZE: usize = 10;
|
||||
|
||||
/// Returns the exact number of bytes this varint will write when
|
||||
/// Returns the exact number of bytes this varlong will write when
|
||||
/// [`Encode::encode`] is called, assuming no error occurs.
|
||||
pub const fn written_size(self) -> usize {
|
||||
match self.0 {
|
||||
|
||||
@ -157,7 +157,7 @@ impl ChunkReader for AnvilChunkReader {
|
||||
.decompress_data(chunk_data)
|
||||
.map_err(ChunkReadingError::Compression)?;
|
||||
|
||||
ChunkData::from_bytes(decompressed_chunk, *at).map_err(ChunkReadingError::ParsingError)
|
||||
ChunkData::from_bytes(&decompressed_chunk, *at).map_err(ChunkReadingError::ParsingError)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -232,15 +232,15 @@ impl Index<ChunkRelativeBlockCoordinates> for ChunkBlocks {
|
||||
}
|
||||
|
||||
impl ChunkData {
|
||||
pub fn from_bytes(chunk_data: Vec<u8>, at: Vector2<i32>) -> Result<Self, ChunkParsingError> {
|
||||
if fastnbt::from_bytes::<ChunkStatus>(&chunk_data)
|
||||
pub fn from_bytes(chunk_data: &[u8], at: Vector2<i32>) -> Result<Self, ChunkParsingError> {
|
||||
if fastnbt::from_bytes::<ChunkStatus>(chunk_data)
|
||||
.map_err(|_| ChunkParsingError::FailedReadStatus)?
|
||||
!= ChunkStatus::Full
|
||||
{
|
||||
return Err(ChunkParsingError::ChunkNotGenerated);
|
||||
}
|
||||
|
||||
let chunk_data = fastnbt::from_bytes::<ChunkNbt>(chunk_data.as_slice())
|
||||
let chunk_data = fastnbt::from_bytes::<ChunkNbt>(chunk_data)
|
||||
.map_err(|e| ChunkParsingError::ErrorDeserializingChunk(e.to_string()))?;
|
||||
|
||||
// this needs to be boxed, otherwise it will cause a stack-overflow
|
||||
|
||||
@ -8,6 +8,7 @@ use crate::{
|
||||
},
|
||||
server::{Server, CURRENT_MC_VERSION},
|
||||
};
|
||||
use core::str;
|
||||
use num_traits::FromPrimitive;
|
||||
use pumpkin_config::{ADVANCED_CONFIG, BASIC_CONFIG};
|
||||
use pumpkin_core::text::TextComponent;
|
||||
@ -412,8 +413,8 @@ impl Client {
|
||||
|| plugin_message.channel.starts_with("MC|Brand")
|
||||
{
|
||||
log::debug!("got a client brand");
|
||||
match String::from_utf8(plugin_message.data) {
|
||||
Ok(brand) => *self.brand.lock().await = Some(brand),
|
||||
match str::from_utf8(&plugin_message.data) {
|
||||
Ok(brand) => *self.brand.lock().await = Some(brand.to_string()),
|
||||
Err(e) => self.kick(&e.to_string()).await,
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user