Skip to content

Instantly share code, notes, and snippets.

@ayosec
Last active April 28, 2020 01:43
Show Gist options
  • Save ayosec/de7d5042d4cfc8724bba106e4fccb8ff to your computer and use it in GitHub Desktop.
Save ayosec/de7d5042d4cfc8724bba106e4fccb8ff to your computer and use it in GitHub Desktop.
trait Handler<Args> {
fn call(self) -> Result<(), ()>;
}
macro_rules! impl_for_tuple {
($($tys:ident),*) => {
impl<F, $($tys,)*> Handler<($($tys,)*)> for F
where
F: FnMut($($tys),*) -> (),
$($tys: std::str::FromStr,)*
$(<$tys as std::str::FromStr>::Err: std::fmt::Debug,)*
{
fn call(mut self) -> Result<(), ()> {
#![allow(non_snake_case)]
$(let $tys = $tys::from_str("0").unwrap();)*
Ok((self)($($tys),*))
}
}
}
}
impl_for_tuple!();
impl_for_tuple!(T0);
impl_for_tuple!(T0, T1);
impl_for_tuple!(T0, T1, T2);
fn run<H, A>(h: H)
where
H: Handler<A>,
{
h.call().unwrap();
}
fn main() {
let mut x = 0;
let mut xs: (u8, u8) = (0, 0);
run(|| x = 1);
run(|a, b| xs = (a, b));
run(|| ());
println!("{}", x);
}
use std::fmt::{self, Display};
use std::str::FromStr;
trait HandlerOutput {}
impl HandlerOutput for () {}
impl<S, E> HandlerOutput for Result<S, E> {}
trait Handler<Args, Output: HandlerOutput> {
type Error: Display;
fn call(self) -> Result<Output, Self::Error>;
}
#[derive(Debug)]
struct ConvertFailed;
impl Display for ConvertFailed {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(fmt, "Invalid value")
}
}
impl std::error::Error for ConvertFailed {}
macro_rules! impl_for_tuple {
($($tys:ident),*) => {
impl<F, O, $($tys,)*> Handler<($($tys,)*), O> for F
where
O: HandlerOutput,
F: FnMut($($tys),*) -> O,
$($tys: FromStr,)*
$(<$tys as FromStr>::Err: Display,)*
{
type Error = ConvertFailed;
fn call(mut self) -> Result<O, Self::Error> {
$(
#[allow(non_snake_case)]
let $tys = match $tys::from_str("0") {
Ok(v) => v,
Err(_) => return Err(ConvertFailed),
};
)*
Ok((self)($($tys),*))
}
}
}
}
impl_for_tuple!();
impl_for_tuple!(T0);
impl_for_tuple!(T0, T1);
impl_for_tuple!(T0, T1, T2);
fn run<H, A, O>(h: H) -> Result<O, H::Error>
where
O: HandlerOutput,
H: Handler<A, O>,
{
h.call()
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut x: isize = -1;
let mut y: isize = -1;
let mut xs: (u8, u8) = (0, 0);
run(|| x = 1)?;
run(|a, b| xs = (a, b))?;
//run(|a| /*-> Result<(), std::num::ParseIntError> */ { y = str::parse(a)?; Ok(()) })?;
//run(|a: usize| Ok::<(), ()>(())?);
println!("{} {}", x, y);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment