nurtex-codec 1.0.0

Library for serializing types from the Minecraft protocol.
Documentation
use std::io::{self, Cursor, Write};
use uuid::Uuid;

use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;

use crate::{Buffer, VarInt, read_str, write_str};

use byteorder::{BE, ReadBytesExt, WriteBytesExt};

impl Buffer for i32 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_i32::<BE>().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_i32::<BE>(*self)
  }
}

impl Buffer for u32 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    Some(i32::read_buf(buffer)? as u32)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    i32::write_buf(&(*self as i32), buffer)
  }
}

impl Buffer for u16 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    i16::read_buf(buffer).map(|i| i as u16)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    i16::write_buf(&(*self as i16), buffer)
  }
}

impl Buffer for i16 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_i16::<BE>().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_i16::<BE>(*self)
  }
}

impl Buffer for i64 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_i64::<BE>().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_i64::<BE>(*self)
  }
}

impl Buffer for u64 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    i64::read_buf(buffer).map(|i| i as u64)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_u64::<BE>(*self)
  }
}

impl Buffer for bool {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let byte = u8::read_buf(buffer)?;

    if byte > 1 {
      return None;
    }

    Some(byte != 0)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    let byte = u8::from(*self);
    byte.write_buf(buffer)
  }
}

impl Buffer for u8 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_u8().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_u8(*self)
  }
}

impl Buffer for i8 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    u8::read_buf(buffer).map(|i| i as i8)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    (*self as u8).write_buf(buffer)
  }
}

impl Buffer for f32 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_f32::<BE>().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_f32::<BE>(*self)
  }
}

impl Buffer for f64 {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    buffer.read_f64::<BE>().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    buffer.write_f64::<BE>(*self)
  }
}

impl<K: Buffer + Eq + Hash, V: Buffer> Buffer for HashMap<K, V> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let length = i32::read_varint(buffer)? as usize;
    let mut contents = HashMap::with_capacity(usize::min(length, 65536));

    for _ in 0..length {
      contents.insert(K::read_buf(buffer)?, V::read_buf(buffer)?);
    }

    Some(contents)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    (self.len() as i32).write_varint(buffer)?;

    for (key, value) in self {
      key.write_buf(buffer)?;
      value.write_buf(buffer)?;
    }

    Ok(())
  }
}

impl<T: Buffer> Buffer for Vec<T> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let length = i32::read_varint(buffer)? as usize;
    let mut contents = Vec::with_capacity(usize::min(length, 65536));

    for _ in 0..length {
      contents.push(T::read_buf(buffer)?);
    }

    Some(contents)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    (self.len() as i32).write_varint(buffer)?;

    for item in self.iter() {
      T::write_buf(item, buffer)?;
    }

    Ok(())
  }
}

impl<T: Buffer> Buffer for Box<[T]> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let length = i32::read_varint(buffer)? as usize;
    let mut contents = Vec::with_capacity(usize::min(length, 65536));

    for _ in 0..length {
      contents.push(T::read_buf(buffer)?);
    }

    Some(contents.into_boxed_slice())
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    (self.len() as i32).write_varint(buffer)?;

    for item in self.iter() {
      T::write_buf(item, buffer)?;
    }

    Ok(())
  }
}

impl Buffer for String {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    read_str(buffer).map(Into::into)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    write_str(buffer, self)
  }
}

impl Buffer for Box<str> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    read_str(buffer).map(Into::into)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    write_str(buffer, self)
  }
}

impl<T: Buffer> Buffer for Option<T> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    if bool::read_buf(buffer)? { Some(T::read_buf(buffer)) } else { None }
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    if let Some(s) = self {
      true.write_buf(buffer)?;
      s.write_buf(buffer)
    } else {
      false.write_buf(buffer)
    }
  }
}

impl<T: Buffer, const N: usize> Buffer for [T; N] {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let mut contents = Vec::with_capacity(N);

    for _ in 0..N {
      contents.push(T::read_buf(buffer)?);
    }

    contents.try_into().ok()
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    for item in self {
      item.write_buf(buffer)?;
    }

    Ok(())
  }
}

impl<T: Buffer> Buffer for Box<T> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    T::read_buf(buffer).map(Box::new)
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    T::write_buf(&**self, buffer)
  }
}

impl<A: Buffer, B: Buffer> Buffer for (A, B) {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    Some((A::read_buf(buffer)?, B::read_buf(buffer)?))
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    self.0.write_buf(buffer)?;
    self.1.write_buf(buffer)
  }
}

impl<T: Buffer> Buffer for Arc<T> {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    Some(Arc::new(T::read_buf(buffer)?))
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    T::write_buf(&**self, buffer)
  }
}

impl Buffer for Uuid {
  fn read_buf(buffer: &mut Cursor<&[u8]>) -> Option<Self> {
    let array = [u32::read_buf(buffer)?, u32::read_buf(buffer)?, u32::read_buf(buffer)?, u32::read_buf(buffer)?];

    let most = ((array[0] as u64) << 32) | ((array[1] as u64) & 0xffffffff);
    let least = ((array[2] as u64) << 32) | ((array[3] as u64) & 0xffffffff);

    Some(Uuid::from_u128(((most as u128) << 64) | least as u128))
  }

  fn write_buf(&self, buffer: &mut impl Write) -> io::Result<()> {
    let most = (self.as_u128() >> 64) as u64;
    let least = (self.as_u128() & 0xffffffffffffffff) as u64;

    let [a, b, c, d] = [(most >> 32) as u32, most as u32, (least >> 32) as u32, least as u32];

    a.write_buf(buffer)?;
    b.write_buf(buffer)?;
    c.write_buf(buffer)?;
    d.write_buf(buffer)?;
    Ok(())
  }
}