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 { fn write(writer: &mut ByteStreamWriter, value: &T) -> Result<()>; fn read(reader: &mut ByteStreamReader<'_>) -> Result; } 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(PhantomData); pub struct List(PhantomData); pub struct NullList(PhantomData); pub struct Arr(PhantomData); pub struct SplitArr(PhantomData); impl Codec for Int { fn write(writer: &mut ByteStreamWriter, value: &i32) -> Result<()> { writer.write_int(*value); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_int() } } impl Codec for VInt { fn write(writer: &mut ByteStreamWriter, value: &i32) -> Result<()> { writer.write_vint(*value); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_vint() } } impl Codec for Byte { fn write(writer: &mut ByteStreamWriter, value: &u8) -> Result<()> { writer.write_byte(*value); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_byte() } } impl Codec for Short { fn write(writer: &mut ByteStreamWriter, value: &i16) -> Result<()> { writer.write_short(*value); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_short() } } impl Codec for Bool { fn write(writer: &mut ByteStreamWriter, value: &bool) -> Result<()> { writer.write_boolean(*value); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_boolean() } } impl Codec> for Str { fn write(writer: &mut ByteStreamWriter, value: &Option) -> Result<()> { writer.write_string(value.as_deref()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result> { reader.read_string() } } impl Codec for StrRef { fn write(writer: &mut ByteStreamWriter, value: &String) -> Result<()> { writer.write_string_reference(value) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { reader.read_string_reference() } } impl Codec for Long { fn write(writer: &mut ByteStreamWriter, value: &LogicLong) -> Result<()> { writer.write_long(value.high, value.low); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { let (high, low) = reader.read_long()?; Ok(LogicLong::new(high, low)) } } impl Codec for VLong { fn write(writer: &mut ByteStreamWriter, value: &LogicLong) -> Result<()> { writer.write_vlong(value.high, value.low); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { let (high, low) = reader.read_vlong()?; Ok(LogicLong::new(high, low)) } } impl Codec>> for Bytes { fn write(writer: &mut ByteStreamWriter, value: &Option>) -> Result<()> { writer.write_bytes(value.as_deref()); Ok(()) } fn read(reader: &mut ByteStreamReader<'_>) -> Result>> { reader.read_bytes() } } impl Codec for Nested { fn write(writer: &mut ByteStreamWriter, value: &T) -> Result<()> { value.encode(writer) } fn read(reader: &mut ByteStreamReader<'_>) -> Result { T::decode(reader) } } impl> Codec> for Opt { fn write(writer: &mut ByteStreamWriter, value: &Option) -> 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> { if reader.read_boolean()? { Ok(Some(C::read(reader)?)) } else { Ok(None) } } } impl> Codec> for List { fn write(writer: &mut ByteStreamWriter, value: &Vec) -> 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> { 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> Codec>> for NullList { fn write(writer: &mut ByteStreamWriter, value: &Option>) -> Result<()> { match value { None => { writer.write_vint(-1); Ok(()) } Some(items) => List::::write(writer, items), } } fn read(reader: &mut ByteStreamReader<'_>) -> Result>> { 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, const N: usize> Codec<[T; N]> for Arr { 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| Error::ArityMismatch { expected: N, actual: items.len(), }) } } impl, const N: usize> Codec<[Option; N]> for SplitArr { fn write(writer: &mut ByteStreamWriter, value: &[Option; 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; 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>| Error::ArityMismatch { expected: N, actual: items.len(), }) } }