#![allow(incomplete_features)]
#![feature(specialization)]
#![deny(clippy::complexity)]
#![deny(clippy::correctness)]
#![deny(clippy::nursery)]
#![deny(clippy::perf)]
#![deny(clippy::style)]
#![deny(clippy::suspicious)]
#![warn(clippy::use_self)]
#![warn(clippy::pedantic)]
#![warn(clippy::cargo)]
#![allow(clippy::doc_markdown)]
#![allow(clippy::wildcard_imports)]
#![allow(clippy::module_name_repetitions)]
use num::Zero;
use std::error::Error;
use thiserror::Error;
pub type ReadResult<T> = Result<T, ReadError>;
pub type WriteResult = Result<(), WriteError>;
pub use bytes::{Buf, BufMut};
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum ReadError {
#[error("unrecognized variant discriminant: {0}")]
UnrecognizedDiscriminant(u8),
#[error("{0}")]
Other(Box<dyn Error>),
}
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum WriteError {
#[error("{0}")]
Other(Box<dyn Error>),
}
pub mod derive {
pub use cornflakes_datasize_macro::{DataSize, StaticDataSize};
}
mod datasize;
mod readable;
mod writable;
pub trait DataSize {
fn data_size(&self) -> usize;
}
pub trait StaticDataSize: DataSize {
fn static_data_size() -> usize
where
Self: Sized;
}
pub trait Readable: DataSize {
fn read_from(reader: &mut impl Buf) -> ReadResult<Self>
where
Self: Sized;
}
pub trait ContextualReadable: DataSize {
type Context;
fn read_with(reader: &mut impl Buf, context: &Self::Context) -> ReadResult<Self>
where
Self: Sized;
}
pub trait Writable: DataSize {
fn write_to(&self, writer: &mut impl BufMut) -> WriteResult;
}
pub trait Wrapper: DataSize {
type WrappedType: Writable + Readable + DataSize + StaticDataSize;
fn wrap(val: Self::WrappedType) -> Self;
fn unwrap(&self) -> &Self::WrappedType;
}
impl<T: Wrapper> Readable for Option<T>
where
T::WrappedType: Zero,
{
fn read_from(buf: &mut impl Buf) -> ReadResult<Self>
where
Self: Sized,
{
Ok(match T::WrappedType::read_from(buf)? {
x if x.is_zero() => None,
val => Some(T::wrap(val)),
})
}
}
impl<T: Wrapper> Writable for Option<T>
where
T::WrappedType: Zero,
{
fn write_to(&self, buf: &mut impl BufMut) -> WriteResult {
match self {
None => T::WrappedType::zero().write_to(buf)?,
Some(val) => val.unwrap().write_to(buf)?,
}
Ok(())
}
}
fn _assert_object_safety(
_data_size: &dyn DataSize,
_static_data_size: &dyn StaticDataSize,
_readable: &dyn Readable,
_contextual_readable: &dyn ContextualReadable<Context = ()>,
) {
}