Skip to content

Instantly share code, notes, and snippets.

@optozorax
Last active June 27, 2020 16:24
Show Gist options
  • Save optozorax/7e39940fe78ffa0a2f482784c8be4858 to your computer and use it in GitHub Desktop.
Save optozorax/7e39940fe78ffa0a2f482784c8be4858 to your computer and use it in GitHub Desktop.
Compile-time arguments for @WaffleLapkin, https://t.me/ihatereality/995
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