Added `subtrait!` macro for creating a blanket-impl trait that ``inherits" from one or more different traits in a few different ways (normal -> `Sized` types only, `dyn`: Sized and unsized types , `virtual`: Sized and unsized types, downcastable.)

Fortune for rsh's current commit: Curse − 凶
specialisation
Avril 3 years ago
parent 2308b61b58
commit ab97278dbd
Signed by: flanchan
GPG Key ID: 284488987C31F630

7
Cargo.lock generated

@ -552,6 +552,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "mopa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915"
[[package]]
name = "net2"
version = "0.2.37"
@ -778,6 +784,7 @@ dependencies = [
"color-eyre",
"cryptohelpers",
"futures",
"mopa",
"pin-project",
"rustc_version",
"serde",

@ -10,6 +10,7 @@ chacha20stream = { version = "1.0.3", features = ["async"] }
color-eyre = "0.5.11"
cryptohelpers = { version = "1.8.1" , features = ["serialise", "full"] }
futures = "0.3.16"
mopa = "0.2.2"
pin-project = "1.0.8"
serde = { version = "1.0.126", features = ["derive"] }
serde_cbor = "0.11.1"

@ -105,3 +105,73 @@ pub fn alloc_local_with_default<T: Default, U>(sz: usize, within: impl FnOnce(&m
stackalloc::stackalloc_with_default(sz, within)
}
}
/// Create a blanket-implementing trait that is a subtrait of any number of traits.
///
/// # Usage
/// To subtype a trait with `Sized` types only:
/// ```
/// # use rsh::subtrait;
/// subtrait!(pub SizedUnpinAsyncRead; "This subtrait must be sized": std::marker::Unpin + tokio::io::AsyncRead);
/// ```
/// To impl the trait for unsized types as well:
/// ```
/// # use rsh::subtrait;
/// subtrait!(pub dyn UnsizedUnpinAsyncRead; "Subtraits `Unpin` and `AsyncRead`. Also implemented for unsized types.": std::marker::Unpin + tokio::io::AsyncRead);
/// ```
/// # Downcastable subtrait
/// To create a subtrait that can be downcasted (correctly coerces to `dyn Any`), use the `virtual` keyword.
/// ```
/// # use rsh::subtrait;
/// subtrait!(pub virtual DowncastableUnpinAsyncRead; "Subtraits `Unpin` and `AsyncRead`. Also dynamically downcastable": std::marker::Unpin + tokio::io::AsyncRead);
/// subtrait!(pub virtual AnotherAny; "A dynamically downcastable trait that subtraits nothing else but `Any`");
/// ```
#[macro_export] macro_rules! subtrait {
(@ $v:vis $name:ident $(; $doc:literal)?: $($t:path),+) => {
$(#[doc = $doc])?
$v trait $name: $($t+)+ {}
};
($v:vis $name:ident $(; $doc:literal)?: $($t:path),+) => {
$crate::subtrait!(@ $v $name $(; $doc)?: Sized, $($t),+);
impl<T: $($t+)+> $name for T{}
};
($v:vis dyn $name:ident $(; $doc:literal)?: $($t:path),+) => {
$crate::subtrait!(@ $v $name $(; $doc)?: $($t),+);
impl<T: ?Sized + $($t+)+> $name for T{}
};
($v:vis virtual $name:ident $(; $doc:literal)?$(: $($t:path),*)?) => {
$crate::subtrait!(@ $v $name $(; $doc)?: ::mopa::Any $(, $($t),*)?);
const _:() = {
fn _assert_object_safe(_: &dyn $name){}
};
mopafy!($name);
impl<T: ?Sized + ::mopa::Any $(+ $($t+)+)?> $name for T {}
};
}
// Static testing of `subtrait`
const _:() = {
use mopa::*;
subtrait!(dyn Test; "test dynamic subtrait": std::marker::Unpin);
subtrait!(virtual TestAny; "test downcastable subtrait of `Read` and `Write`": std::io::Read);
subtrait!(virtual TestAny2; "test downcastable subtrait of only `Any`");
const fn _a<T: Test+?Sized>(){}
const fn _b<T: TestAny+?Sized>(){}
fn _c(a: Box<dyn TestAny>)
{
if a.is::<std::io::Stdin>() {
let _ref: &std::io::Stdin = a.downcast_ref::<std::io::Stdin>().unwrap();
drop(_ref);
let _unbox: std::io::Stdin = *a.downcast().map_err(|_| ()).unwrap();
}
}
fn _d(a: &dyn TestAny)
{
if a.is::<std::io::Stdin>() {
let _ref: &std::io::Stdin = a.downcast_ref::<std::io::Stdin>().unwrap();
}
}
const _TEST: () = _a::<dyn Test>();
const _TEST2: () = _b::<dyn TestAny>();
};

@ -9,8 +9,10 @@ use tokio::task::JoinHandle;
use futures::Future;
use cancel::*;
/// Handles a raw socket
pub fn handle_socket_with_shutdown<R, W, C: cancel::CancelFuture + 'static + Send>(sock_read: R, sock_write: W, shutdown: C) -> JoinHandle<eyre::Result<()>>
/// Handles a raw, opened socket
pub fn handle_socket_with_shutdown<R, W, C: cancel::CancelFuture + 'static + Send>(tx: W, rx: R, shutdown: C) -> JoinHandle<eyre::Result<()>>
where R: AsyncRead + Unpin + Send + 'static,
W: AsyncWrite + Unpin + Send + 'static
{

Loading…
Cancel
Save