scroll.server/crates/titan/src/codec.rs
WiseDev d25a6de423 move all crates into crates/, glob members
pure move, no code touched. readme and protocol.md paths fixed up.
2026-08-23 08:15:45 +03:00

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(),
})
}
}