Last active
June 27, 2020 16:24
-
-
Save optozorax/7e39940fe78ffa0a2f482784c8be4858 to your computer and use it in GitHub Desktop.
Compile-time arguments for @WaffleLapkin, https://t.me/ihatereality/995
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::io::Write; | |
use std::io::stdout; | |
use std::io::stdin; | |
#[derive(Debug)] | |
struct A { | |
a: i32, | |
} | |
#[derive(Debug)] | |
struct B { | |
b: f32, | |
} | |
trait RequestField: std::marker::Sized { | |
fn for_get() -> String; | |
fn parse(s: &str) -> Option<Self>; | |
} | |
impl RequestField for A { | |
fn for_get() -> String { | |
"i32".to_string() | |
} | |
fn parse(s: &str) -> Option<Self> { | |
Some( | |
Self { | |
a: s.parse().ok()? | |
} | |
) | |
} | |
} | |
impl RequestField for B { | |
fn for_get() -> String { | |
"f32".to_string() | |
} | |
fn parse(s: &str) -> Option<Self> { | |
Some( | |
Self { | |
b: s.parse().ok()? | |
} | |
) | |
} | |
} | |
struct Nil; | |
struct Cons<A, B>(A, B); | |
impl RequestField for Nil { | |
fn for_get() -> String { | |
"".to_string() | |
} | |
fn parse(_: &str) -> Option<Self> { | |
Some(Nil) | |
} | |
} | |
impl<A: RequestField, B: RequestField> RequestField for Cons<A, B> { | |
fn for_get() -> String { | |
format!("{}, {}", <A as RequestField>::for_get(), <B as RequestField>::for_get()) | |
} | |
fn parse(s: &str) -> Option<Self> { | |
let first_s: &str = &(*(s.split(',').next()?)); | |
let next = first_s.len() + ','.len_utf8(); | |
let second_s = if next > s.len() { | |
"" | |
} else { | |
&s[next..] | |
}; | |
Some( | |
Cons( | |
<A as RequestField>::parse(first_s)?, | |
<B as RequestField>::parse(second_s)?, | |
) | |
) | |
} | |
} | |
fn api_get<T: RequestField>() -> Option<T> { | |
print!("Please input {}: ", <T as RequestField>::for_get()); | |
let mut s = String::new(); | |
let _ = stdout().flush(); | |
stdin().read_line(&mut s).expect("Did not enter a correct string"); | |
if let Some('\n')=s.chars().next_back() { s.pop(); } | |
if let Some('\r')=s.chars().next_back() { s.pop(); } | |
<T as RequestField>::parse(&s) | |
} | |
macro_rules! hlist_let { | |
($a: ident, $($tail:tt)*) => { Cons($a, hlist_let![$($tail)*]) }; | |
($a: ident) => { Cons($a, _) }; | |
} | |
macro_rules! hlist_type { | |
($a: ident, $($tail:tt)*) => { Cons<$a, hlist_type![$($tail)*]> }; | |
($a: ident) => { Cons<$a, Nil> }; | |
} | |
fn main() { | |
let hlist_let![a, b, c] = | |
api_get::<hlist_type![A, B, B]>() | |
.expect("incorect input"); | |
dbg!(a, b, c); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment