in midst of refactor

This commit is contained in:
2024-04-29 21:46:42 +02:00
parent ed0d64d52e
commit aa3f7e99ab
221 changed files with 5431 additions and 685 deletions

View File

@@ -0,0 +1,266 @@
use std::collections::HashMap;
use std::hash::Hash;
use std::io::{Read, Write};
use std::iter;
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;
use ordered_float::{FloatCore, NotNan};
use crate::encode_enum;
pub trait Decode {
/// Decode an instance from the beginning of the buffer. Return the decoded
/// data and the remaining buffer.
fn decode<R: Read>(read: &mut R) -> Self;
}
pub trait Encode {
/// Append an instance of the struct to the buffer
fn encode<W: Write>(&self, write: &mut W);
fn enc_vec(&self) -> Vec<u8> {
let mut vec = Vec::new();
self.encode(&mut vec);
vec
}
}
pub trait Coding: Encode + Decode {}
impl<T: Encode + Decode> Coding for T {}
macro_rules! num_impl {
($number:ty, $size:expr) => {
impl Decode for $number {
fn decode<R: Read>(read: &mut R) -> Self {
let mut bytes = [0u8; $size];
read.read_exact(&mut bytes).unwrap();
<$number>::from_be_bytes(bytes)
}
}
impl Encode for $number {
fn encode<W: Write>(&self, write: &mut W) {
write.write_all(&self.to_be_bytes()).expect("Could not write number")
}
}
};
($number:ty) => {
num_impl!($number, (<$number>::BITS / 8) as usize);
};
}
num_impl!(u128);
num_impl!(u64);
num_impl!(u32);
num_impl!(u16);
num_impl!(u8);
num_impl!(i128);
num_impl!(i64);
num_impl!(i32);
num_impl!(i16);
num_impl!(i8);
num_impl!(f64, 8);
num_impl!(f32, 4);
macro_rules! nonzero_impl {
($name:ty) => {
impl Decode for $name {
fn decode<R: Read>(read: &mut R) -> Self { Self::new(Decode::decode(read)).unwrap() }
}
impl Encode for $name {
fn encode<W: Write>(&self, write: &mut W) { self.get().encode(write) }
}
};
}
nonzero_impl!(std::num::NonZeroU8);
nonzero_impl!(std::num::NonZeroU16);
nonzero_impl!(std::num::NonZeroU32);
nonzero_impl!(std::num::NonZeroU64);
nonzero_impl!(std::num::NonZeroU128);
nonzero_impl!(std::num::NonZeroI8);
nonzero_impl!(std::num::NonZeroI16);
nonzero_impl!(std::num::NonZeroI32);
nonzero_impl!(std::num::NonZeroI64);
nonzero_impl!(std::num::NonZeroI128);
impl<'a, T: Encode> Encode for &'a T {
fn encode<W: Write>(&self, write: &mut W) { (**self).encode(write) }
}
impl<T: Decode + FloatCore> Decode for NotNan<T> {
fn decode<R: Read>(read: &mut R) -> Self { NotNan::new(T::decode(read)).expect("Float was NaN") }
}
impl<T: Encode + FloatCore> Encode for NotNan<T> {
fn encode<W: Write>(&self, write: &mut W) { self.as_ref().encode(write) }
}
impl Decode for String {
fn decode<R: Read>(read: &mut R) -> Self {
let len = u64::decode(read).try_into().unwrap();
let mut data = vec![0u8; len];
read.read_exact(&mut data).unwrap();
std::str::from_utf8(&data).expect("String invalid UTF-8").to_owned()
}
}
impl Encode for String {
fn encode<W: Write>(&self, write: &mut W) {
u64::try_from(self.len()).unwrap().encode(write);
write.write_all(self.as_bytes()).unwrap()
}
}
impl Encode for str {
fn encode<W: Write>(&self, write: &mut W) {
u64::try_from(self.len()).unwrap().encode(write);
write.write_all(self.as_bytes()).unwrap()
}
}
impl<T: Decode> Decode for Vec<T> {
fn decode<R: Read>(read: &mut R) -> Self {
let len = u64::decode(read).try_into().unwrap();
iter::repeat_with(|| T::decode(read)).take(len).collect()
}
}
impl<T: Encode> Encode for Vec<T> {
fn encode<W: Write>(&self, write: &mut W) {
u64::try_from(self.len()).unwrap().encode(write);
self.iter().for_each(|t| t.encode(write));
}
}
impl<T: Encode> Encode for [T] {
fn encode<W: Write>(&self, write: &mut W) {
u64::try_from(self.len()).unwrap().encode(write);
self.iter().for_each(|t| t.encode(write));
}
}
impl<T: Decode> Decode for Option<T> {
fn decode<R: Read>(read: &mut R) -> Self {
match u8::decode(read) {
0 => None,
1 => Some(T::decode(read)),
x => panic!("{x} is not a valid option value"),
}
}
}
impl<T: Encode> Encode for Option<T> {
fn encode<W: Write>(&self, write: &mut W) {
let t = if let Some(t) = self { t } else { return 0u8.encode(write) };
1u8.encode(write);
t.encode(write);
}
}
impl<T: Decode, E: Decode> Decode for Result<T, E> {
fn decode<R: Read>(read: &mut R) -> Self {
match u8::decode(read) {
0 => Self::Ok(T::decode(read)),
1 => Self::Err(E::decode(read)),
x => panic!("Invalid Result tag {x}"),
}
}
}
impl<T: Encode, E: Encode> Encode for Result<T, E> {
fn encode<W: Write>(&self, write: &mut W) {
match self {
Ok(t) => encode_enum(write, 0, |w| t.encode(w)),
Err(e) => encode_enum(write, 1, |w| e.encode(w)),
}
}
}
impl<K: Decode + Eq + Hash, V: Decode> Decode for HashMap<K, V> {
fn decode<R: Read>(read: &mut R) -> Self {
let len = u64::decode(read).try_into().unwrap();
iter::repeat_with(|| <(K, V)>::decode(read)).take(len).collect()
}
}
impl<K: Encode + Eq + Hash, V: Encode> Encode for HashMap<K, V> {
fn encode<W: Write>(&self, write: &mut W) {
u64::try_from(self.len()).unwrap().encode(write);
self.iter().for_each(|pair| pair.encode(write));
}
}
macro_rules! tuple {
(($($t:ident)*) ($($T:ident)*)) => {
impl<$($T: Decode),*> Decode for ($($T,)*) {
fn decode<R: Read>(read: &mut R) -> Self { ($($T::decode(read),)*) }
}
impl<$($T: Encode),*> Encode for ($($T,)*) {
fn encode<W: Write>(&self, write: &mut W) {
let ($($t,)*) = self;
$( $t.encode(write); )*
}
}
};
}
tuple!((t)(T));
tuple!((t u) (T U));
tuple!((t u v) (T U V));
tuple!((t u v x) (T U V X)); // 4
tuple!((t u v x y) (T U V X Y));
tuple!((t u v x y z) (T U V X Y Z));
tuple!((t u v x y z a) (T U V X Y Z A));
tuple!((t u v x y z a b) (T U V X Y Z A B)); // 8
tuple!((t u v x y z a b c) (T U V X Y Z A B C));
tuple!((t u v x y z a b c d) (T U V X Y Z A B C D));
tuple!((t u v x y z a b c d e) (T U V X Y Z A B C D E));
tuple!((t u v x y z a b c d e f) (T U V X Y Z A B C D E F)); // 12
tuple!((t u v x y z a b c d e f g) (T U V X Y Z A B C D E F G));
tuple!((t u v x y z a b c d e f g h) (T U V X Y Z A B C D E F G H));
tuple!((t u v x y z a b c d e f g h i) (T U V X Y Z A B C D E F G H I));
tuple!((t u v x y z a b c d e f g h i j) (T U V X Y Z A B C D E F G H I J)); // 16
impl Decode for () {
fn decode<R: Read>(_: &mut R) -> Self {}
}
impl Encode for () {
fn encode<W: Write>(&self, _: &mut W) {}
}
impl Decode for bool {
fn decode<R: Read>(read: &mut R) -> Self {
let mut buf = [0];
read.read_exact(&mut buf).unwrap();
buf[0] != 0
}
}
impl Encode for bool {
fn encode<W: Write>(&self, write: &mut W) {
write.write_all(&[if *self { 0xff } else { 0 }]).unwrap()
}
}
impl<T: Decode, const N: usize> Decode for [T; N] {
fn decode<R: Read>(read: &mut R) -> Self {
// TODO: figure out how to do this in safe rust on the stack
((0..N).map(|_| T::decode(read)).collect::<Vec<_>>().try_into())
.unwrap_or_else(|_| unreachable!("The length of this iterator is statically known"))
}
}
impl<T: Encode, const N: usize> Encode for [T; N] {
fn encode<W: Write>(&self, write: &mut W) { self.iter().for_each(|t| t.encode(write)) }
}
impl<T: Decode> Decode for Range<T> {
fn decode<R: Read>(read: &mut R) -> Self { T::decode(read)..T::decode(read) }
}
impl<T: Encode> Encode for Range<T> {
fn encode<W: Write>(&self, write: &mut W) {
self.start.encode(write);
self.end.encode(write);
}
}
macro_rules! smart_ptr {
($name:tt) => {
impl<T: Decode> Decode for $name<T> {
fn decode<R: Read>(read: &mut R) -> Self { $name::new(T::decode(read)) }
}
impl<T: Encode> Encode for $name<T> {
fn encode<W: Write>(&self, write: &mut W) { (**self).encode(write) }
}
};
}
smart_ptr!(Arc);
smart_ptr!(Rc);
smart_ptr!(Box);
impl Decode for char {
fn decode<R: Read>(read: &mut R) -> Self { char::from_u32(u32::decode(read)).unwrap() }
}
impl Encode for char {
fn encode<W: Write>(&self, write: &mut W) { (*self as u32).encode(write) }
}

View File

@@ -0,0 +1,18 @@
use std::io::{Read, Write};
use crate::Encode;
pub fn encode_enum<W: Write>(write: &mut W, id: u8, f: impl FnOnce(&mut W)) {
id.encode(write);
f(write)
}
pub fn write_exact(write: &mut impl Write, bytes: &'static [u8]) {
write.write_all(bytes).expect("Failed to write exact bytes")
}
pub fn read_exact(read: &mut impl Read, bytes: &'static [u8]) {
let mut data = vec![0u8; bytes.len()];
read.read_exact(&mut data).expect("Failed to read bytes");
assert_eq!(&data, bytes, "Wrong bytes")
}

View File

@@ -0,0 +1,30 @@
pub trait TBool {}
pub struct TTrue;
impl TBool for TTrue {}
pub struct TFalse;
impl TBool for TFalse {}
/// Implementation picker for a tree node
///
/// Note: This technically allows for the degenerate case
/// ```
/// struct MyType;
/// impl TreeRolePicker for MyType {
/// type IsLeaf = TTrue;
/// type IsRoot = TTrue;
/// }
/// ```
/// This isn't very useful because it describes a one element sealed hierarchy.
pub trait TreeRolePicker {
type IsLeaf: TBool;
type IsRoot: TBool;
}
pub trait Extends: TreeRolePicker<IsRoot = TFalse> {
type Parent: TreeRolePicker<IsLeaf = TFalse>;
}
pub trait Inherits<T> {}
// impl<T> Inherits<T, 0> for T {}
impl<T: Extends, This> Inherits<T::Parent> for This where This: Inherits<T> {}

View File

@@ -0,0 +1,80 @@
/// [Hierarchy] implementation key. The two implementors of this trait are
/// [Base] and [Subtype]. These types are assigned to [InHierarchy::Role] to
/// select the implementation of [Hierarchy].
pub trait HierarchyRole {}
/// A type-level boolean suitable to select conditional trait implementations.
/// Implementors are [True] and [False]
pub trait TLBool {}
/// [TLBool] value of `true`. The opposite is [False]
pub struct TLTrue;
impl TLBool for TLTrue {}
/// [TLBool] value of `false`. The opposite is [True]
pub struct TLFalse;
impl TLBool for TLFalse {}
/// Assign this type to [InHierarchy::Role] and implement [Descendant] to create
/// a subtype. These types can be upcast to their parent type, conditionally
/// downcast from it, and selected for [Descendant::Parent] by other types.
pub struct Subtype;
impl HierarchyRole for Subtype {}
/// Assign this type to [InHierarchy::Role] to create a base type. These types
/// are upcast only to themselves, but they can be selected in
/// [Descendant::Parent].
pub struct Base;
impl HierarchyRole for Base {}
/// A type that implements [Hierarchy]. Used to select implementations of traits
/// on the hierarchy
pub trait InHierarchy: Clone {
/// Indicates that this hierarchy element is a leaf. Leaves can never have
/// children
type IsLeaf: TLBool;
/// Indicates that this hierarchy element is a root. Roots can never have
/// parents
type IsRoot: TLBool;
}
/// A type that derives from a parent type.
pub trait Extends: InHierarchy<IsRoot = TLFalse> + Into<Self::Parent> {
/// Specify the immediate parent of this type. This guides the
type Parent: InHierarchy<IsLeaf = TLFalse>
+ TryInto<Self>
+ UnderRootImpl<<Self::Parent as InHierarchy>::IsRoot>;
}
pub trait UnderRootImpl<IsRoot: TLBool>: Sized {
type __Root: UnderRoot<IsRoot = TLTrue, Root = Self::__Root>;
fn __into_root(self) -> Self::__Root;
fn __try_from_root(root: Self::__Root) -> Result<Self, Self::__Root>;
}
pub trait UnderRoot: InHierarchy {
type Root: UnderRoot<IsRoot = TLTrue, Root = Self::Root>;
fn into_root(self) -> Self::Root;
fn try_from_root(root: Self::Root) -> Result<Self, Self::Root>;
}
impl<T: InHierarchy + UnderRootImpl<T::IsRoot>> UnderRoot for T {
type Root = <Self as UnderRootImpl<<Self as InHierarchy>::IsRoot>>::__Root;
fn into_root(self) -> Self::Root { self.__into_root() }
fn try_from_root(root: Self::Root) -> Result<Self, Self::Root> { Self::__try_from_root(root) }
}
impl<T: InHierarchy<IsRoot = TLTrue>> UnderRootImpl<TLTrue> for T {
type __Root = Self;
fn __into_root(self) -> Self::__Root { self }
fn __try_from_root(root: Self::__Root) -> Result<Self, Self::__Root> { Ok(root) }
}
impl<T: InHierarchy<IsRoot = TLFalse> + Extends> UnderRootImpl<TLFalse> for T {
type __Root = <<Self as Extends>::Parent as UnderRootImpl<
<<Self as Extends>::Parent as InHierarchy>::IsRoot,
>>::__Root;
fn __into_root(self) -> Self::__Root {
<Self as Into<<Self as Extends>::Parent>>::into(self).into_root()
}
fn __try_from_root(root: Self::__Root) -> Result<Self, Self::__Root> {
let parent = <Self as Extends>::Parent::try_from_root(root)?;
parent.clone().try_into().map_err(|_| parent.into_root())
}
}

View File

@@ -0,0 +1,12 @@
mod coding;
mod helpers;
mod hierarchy;
mod relations;
pub use coding::{Coding, Decode, Encode};
pub use helpers::{encode_enum, read_exact, write_exact};
pub use hierarchy::{
Base, Extends, HierarchyRole, InHierarchy, Subtype, TLBool, TLFalse, TLTrue, UnderRoot,
UnderRootImpl,
};
pub use relations::{MsgSet, Request};

View File

@@ -0,0 +1,13 @@
use super::coding::{Coding, Encode};
pub trait Request: Coding + Sized + Send + 'static {
type Response: Coding + Send + 'static;
fn respond(&self, rep: Self::Response) -> Vec<u8> { rep.enc_vec() }
}
pub trait MsgSet {
type InReq: Coding + Sized + Send + 'static;
type InNot: Coding + Sized + Send + 'static;
type OutReq: Coding + Sized + Send + 'static;
type OutNot: Coding + Sized + Send + 'static;
}