257 lines
7.8 KiB
Rust
257 lines
7.8 KiB
Rust
use std::marker::PhantomData;
|
|
use crate::error::{Error, Result};
|
|
use crate::io::{ByteStreamReader, ByteStreamWriter, MAX_COLLECTION_LEN};
|
|
use crate::logic_long::LogicLong;
|
|
use crate::message::Payload;
|
|
pub trait Codec<T> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &T) -> Result<()>;
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<T>;
|
|
}
|
|
pub struct Int;
|
|
pub struct VInt;
|
|
pub struct Byte;
|
|
pub struct Short;
|
|
pub struct Bool;
|
|
pub struct Str;
|
|
pub struct StrRef;
|
|
pub struct Long;
|
|
pub struct VLong;
|
|
pub struct Bytes;
|
|
pub struct Nested;
|
|
pub struct Opt<C>(PhantomData<C>);
|
|
pub struct List<C>(PhantomData<C>);
|
|
pub struct NullList<C>(PhantomData<C>);
|
|
pub struct Arr<C, const N: usize>(PhantomData<C>);
|
|
pub struct SplitArr<C, const N: usize>(PhantomData<C>);
|
|
impl Codec<i32> for Int {
|
|
fn write(writer: &mut ByteStreamWriter, value: &i32) -> Result<()> {
|
|
writer.write_int(*value);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<i32> {
|
|
reader.read_int()
|
|
}
|
|
}
|
|
impl Codec<i32> for VInt {
|
|
fn write(writer: &mut ByteStreamWriter, value: &i32) -> Result<()> {
|
|
writer.write_vint(*value);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<i32> {
|
|
reader.read_vint()
|
|
}
|
|
}
|
|
impl Codec<u8> for Byte {
|
|
fn write(writer: &mut ByteStreamWriter, value: &u8) -> Result<()> {
|
|
writer.write_byte(*value);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<u8> {
|
|
reader.read_byte()
|
|
}
|
|
}
|
|
impl Codec<i16> for Short {
|
|
fn write(writer: &mut ByteStreamWriter, value: &i16) -> Result<()> {
|
|
writer.write_short(*value);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<i16> {
|
|
reader.read_short()
|
|
}
|
|
}
|
|
impl Codec<bool> for Bool {
|
|
fn write(writer: &mut ByteStreamWriter, value: &bool) -> Result<()> {
|
|
writer.write_boolean(*value);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<bool> {
|
|
reader.read_boolean()
|
|
}
|
|
}
|
|
impl Codec<Option<String>> for Str {
|
|
fn write(writer: &mut ByteStreamWriter, value: &Option<String>) -> Result<()> {
|
|
writer.write_string(value.as_deref())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<Option<String>> {
|
|
reader.read_string()
|
|
}
|
|
}
|
|
impl Codec<String> for StrRef {
|
|
fn write(writer: &mut ByteStreamWriter, value: &String) -> Result<()> {
|
|
writer.write_string_reference(value)
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<String> {
|
|
reader.read_string_reference()
|
|
}
|
|
}
|
|
impl Codec<LogicLong> for Long {
|
|
fn write(writer: &mut ByteStreamWriter, value: &LogicLong) -> Result<()> {
|
|
writer.write_long(value.high, value.low);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<LogicLong> {
|
|
let (high, low) = reader.read_long()?;
|
|
Ok(LogicLong::new(high, low))
|
|
}
|
|
}
|
|
impl Codec<LogicLong> for VLong {
|
|
fn write(writer: &mut ByteStreamWriter, value: &LogicLong) -> Result<()> {
|
|
writer.write_vlong(value.high, value.low);
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<LogicLong> {
|
|
let (high, low) = reader.read_vlong()?;
|
|
Ok(LogicLong::new(high, low))
|
|
}
|
|
}
|
|
impl Codec<Option<Vec<u8>>> for Bytes {
|
|
fn write(writer: &mut ByteStreamWriter, value: &Option<Vec<u8>>) -> Result<()> {
|
|
writer.write_bytes(value.as_deref());
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<Option<Vec<u8>>> {
|
|
reader.read_bytes()
|
|
}
|
|
}
|
|
impl<T: Payload> Codec<T> for Nested {
|
|
fn write(writer: &mut ByteStreamWriter, value: &T) -> Result<()> {
|
|
value.encode(writer)
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<T> {
|
|
T::decode(reader)
|
|
}
|
|
}
|
|
impl<T, C: Codec<T>> Codec<Option<T>> for Opt<C> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &Option<T>) -> Result<()> {
|
|
match value {
|
|
None => {
|
|
writer.write_boolean(false);
|
|
Ok(())
|
|
}
|
|
Some(inner) => {
|
|
writer.write_boolean(true);
|
|
C::write(writer, inner)
|
|
}
|
|
}
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<Option<T>> {
|
|
if reader.read_boolean()? {
|
|
Ok(Some(C::read(reader)?))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
}
|
|
impl<T, C: Codec<T>> Codec<Vec<T>> for List<C> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &Vec<T>) -> Result<()> {
|
|
if value.len() > MAX_COLLECTION_LEN {
|
|
return Err(Error::CollectionTooLarge {
|
|
actual: value.len(),
|
|
limit: MAX_COLLECTION_LEN,
|
|
});
|
|
}
|
|
writer.write_vint(value.len() as i32);
|
|
for item in value {
|
|
C::write(writer, item)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<Vec<T>> {
|
|
let count = reader.read_vint()?;
|
|
if count < 0 {
|
|
return Err(Error::NegativeLength(count));
|
|
}
|
|
let count = count as usize;
|
|
if count > MAX_COLLECTION_LEN {
|
|
return Err(Error::CollectionTooLarge {
|
|
actual: count,
|
|
limit: MAX_COLLECTION_LEN,
|
|
});
|
|
}
|
|
let mut items = Vec::with_capacity(count.min(1024));
|
|
for _ in 0..count {
|
|
items.push(C::read(reader)?);
|
|
}
|
|
Ok(items)
|
|
}
|
|
}
|
|
impl<T, C: Codec<T>> Codec<Option<Vec<T>>> for NullList<C> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &Option<Vec<T>>) -> Result<()> {
|
|
match value {
|
|
None => {
|
|
writer.write_vint(-1);
|
|
Ok(())
|
|
}
|
|
Some(items) => List::<C>::write(writer, items),
|
|
}
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<Option<Vec<T>>> {
|
|
let count = reader.read_vint()?;
|
|
if count < 0 {
|
|
return Ok(None);
|
|
}
|
|
let count = count as usize;
|
|
if count > MAX_COLLECTION_LEN {
|
|
return Err(Error::CollectionTooLarge {
|
|
actual: count,
|
|
limit: MAX_COLLECTION_LEN,
|
|
});
|
|
}
|
|
let mut items = Vec::with_capacity(count.min(1024));
|
|
for _ in 0..count {
|
|
items.push(C::read(reader)?);
|
|
}
|
|
Ok(Some(items))
|
|
}
|
|
}
|
|
impl<T, C: Codec<T>, const N: usize> Codec<[T; N]> for Arr<C, N> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &[T; N]) -> Result<()> {
|
|
for item in value {
|
|
C::write(writer, item)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<[T; N]> {
|
|
let mut items = Vec::with_capacity(N);
|
|
for _ in 0..N {
|
|
items.push(C::read(reader)?);
|
|
}
|
|
items
|
|
.try_into()
|
|
.map_err(|items: Vec<T>| Error::ArityMismatch {
|
|
expected: N,
|
|
actual: items.len(),
|
|
})
|
|
}
|
|
}
|
|
impl<T, C: Codec<T>, const N: usize> Codec<[Option<T>; N]> for SplitArr<C, N> {
|
|
fn write(writer: &mut ByteStreamWriter, value: &[Option<T>; N]) -> Result<()> {
|
|
for slot in value {
|
|
writer.write_boolean(slot.is_some());
|
|
}
|
|
for slot in value.iter().flatten() {
|
|
C::write(writer, slot)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
fn read(reader: &mut ByteStreamReader<'_>) -> Result<[Option<T>; N]> {
|
|
let mut present = [false; N];
|
|
for slot in present.iter_mut() {
|
|
*slot = reader.read_boolean()?;
|
|
}
|
|
let mut items = Vec::with_capacity(N);
|
|
for occupied in present {
|
|
items.push(if occupied {
|
|
Some(C::read(reader)?)
|
|
} else {
|
|
None
|
|
});
|
|
}
|
|
items
|
|
.try_into()
|
|
.map_err(|items: Vec<Option<T>>| Error::ArityMismatch {
|
|
expected: N,
|
|
actual: items.len(),
|
|
})
|
|
}
|
|
}
|