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:
26
orchid-api-traits/src/api_conv.rs
Normal file
26
orchid-api-traits/src/api_conv.rs
Normal 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) }
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user