Began implementing fully isomorphic macros

Like Rust's Proc macros. Now we have preprocessor recursion to worry about. I also made a cool macro for enums
This commit is contained in:
2024-10-14 00:13:09 +02:00
parent 84cbcdd4fe
commit 3a3ae98aff
66 changed files with 2302 additions and 1164 deletions

View File

@@ -0,0 +1,26 @@
pub trait ApiEquiv {
type Api;
}
pub trait ToApi: Sized + ApiEquiv {
type Ctx;
fn to_api(&self, ctx: &mut Self::Ctx) -> Self::Api;
fn into_api(self, ctx: &mut Self::Ctx) -> Self::Api { self.to_api(ctx) }
}
pub trait FromApi: ApiEquiv {
type Ctx;
fn from_api(api: &Self::Api, ctx: &mut Self::Ctx) -> Self;
}
/// This is the weakest kind of conversion possible;
/// By holding a reference to the source type, you can provide a reference to the target type.
/// Unlike Into, the target type may hold references into the source,
/// but unlike AsRef, it doesn't have to be fully contained in the source.
/// The resulting object is stackbound so its utility is very limited.
pub trait ProjectionMut<T> {
fn with_built<R>(&mut self, cb: impl FnOnce(&mut T) -> R) -> R;
}
impl<T> ProjectionMut<T> for T {
fn with_built<R>(&mut self, cb: impl FnOnce(&mut T) -> R) -> R { cb(self) }
}

View File

@@ -1,5 +1,7 @@
use std::io::{Read, Write};
use itertools::{Chunk, Itertools};
use crate::Encode;
pub fn encode_enum<W: Write + ?Sized>(write: &mut W, id: u8, f: impl FnOnce(&mut W)) {
@@ -11,10 +13,20 @@ pub fn write_exact<W: Write + ?Sized>(write: &mut W, bytes: &'static [u8]) {
write.write_all(bytes).expect("Failed to write exact bytes")
}
pub fn print_bytes(b: &[u8]) -> String {
(b.iter().map(|b| format!("{b:02x}")))
.chunks(4)
.into_iter()
.map(|mut c: Chunk<_>| c.join(" "))
.join(" ")
}
pub fn read_exact<R: Read + ?Sized>(read: &mut R, 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")
if data != bytes {
panic!("Wrong bytes!\nExpected: {}\nFound: {}", print_bytes(bytes), print_bytes(&data));
}
}
pub fn enc_vec(enc: &impl Encode) -> Vec<u8> {

View File

@@ -2,8 +2,10 @@ mod coding;
mod helpers;
mod hierarchy;
mod relations;
mod api_conv;
pub use coding::{Coding, Decode, Encode};
pub use helpers::{enc_vec, encode_enum, read_exact, write_exact};
pub use hierarchy::{Extends, InHierarchy, TLBool, TLFalse, TLTrue, UnderRoot};
pub use relations::{Channel, MsgSet, Request};
pub use coding::*;
pub use helpers::*;
pub use hierarchy::*;
pub use relations::*;
pub use api_conv::*;

View File

@@ -3,7 +3,11 @@ use crate::helpers::enc_vec;
pub trait Request: Coding + Sized + Send + 'static {
type Response: Coding + Send + 'static;
fn respond(&self, rep: Self::Response) -> Vec<u8> { enc_vec(&rep) }
}
pub fn respond<R: Request>(_: &R, rep: R::Response) -> Vec<u8> { enc_vec(&rep) }
pub fn respond_with<R: Request>(r: &R, f: impl FnOnce(&R) -> R::Response) -> Vec<u8> {
respond(r, f(r))
}
pub trait Channel: 'static {