Skip to content

Commit 6a88197

Browse files
committed
handle fallible generators
1 parent 13e3f8d commit 6a88197

File tree

6 files changed

+96
-23
lines changed

6 files changed

+96
-23
lines changed

.github/workflows/tests.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,6 @@ jobs:
2626

2727
- name: Format
2828
run: cargo fmt -- --check
29+
30+
- name: Run example
31+
run: echo "42" | cargo run --bin example -- -i

src/input.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn get_input(year: u16, day: u8) -> Result<String, Box<dyn Error>> {
1919
.send()?;
2020
let elapsed = start.elapsed();
2121

22-
crate::print_with_duration("downloaded input file", None, elapsed);
22+
crate::print_with_duration("downloaded input file", None, Some(elapsed));
2323
resp.text()
2424
})?;
2525

src/lib.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pub mod input;
22
pub mod parse;
33
pub mod run;
4+
pub mod try_unwrap;
45

56
use std::cmp::min;
67
use std::iter;
@@ -9,16 +10,20 @@ use std::time::Duration;
910

1011
// Reexport some crates for the generated main
1112
pub use clap;
13+
pub use colored;
1214
pub use criterion;
1315

1416
use clap::Clap;
1517
use colored::*;
1618

1719
const DISPLAY_WIDTH: usize = 40;
1820

19-
pub fn print_with_duration(line: &str, output: Option<&str>, duration: Duration) {
20-
let duration = format!("({:.2?})", duration);
21-
print!(" - {} {}", line, duration.dimmed());
21+
pub fn print_with_duration(line: &str, output: Option<ColoredString>, duration: Option<Duration>) {
22+
let duration = duration
23+
.map(|duration| format!(" ({:.2?})", duration))
24+
.unwrap_or_else(String::new);
25+
26+
print!(" - {}{}", line, duration.dimmed());
2227

2328
if let Some(output) = output {
2429
let width = " - ".len() + line.chars().count() + 1 + duration.chars().count();

src/parse.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,28 @@
22
// $ctx, { day DAY { { gen GENERATOR } { { sol SOLUTION } { sol SOLUTION } } } }
33
#[macro_export]
44
macro_rules! parse {
5-
// Read day
5+
// Read day: default generator
6+
(
7+
day $apply: ident, $ctx: tt, $val: expr;
8+
$day: ident => $( $tail: tt )*
9+
) => {
10+
$crate::parse!( sol $apply, $ctx, $val; { day $day { { gen_default } { } } }; $( $tail )* )
11+
};
12+
13+
// Read day: regular generator
614
(
715
day $apply: ident, $ctx: tt, $val: expr;
816
$day: ident : $generator: ident => $( $tail: tt )*
917
) => {
1018
$crate::parse!( sol $apply, $ctx, $val; { day $day { { gen $generator } { } } }; $( $tail )* )
1119
};
1220

13-
// Read day: default generator
21+
// Read day: fallible generator
1422
(
1523
day $apply: ident, $ctx: tt, $val: expr;
16-
$day: ident => $( $tail: tt )*
24+
$day: ident : $generator: ident ? => $( $tail: tt )*
1725
) => {
18-
$crate::parse!( sol $apply, $ctx, $val; { day $day { { gen_default } { } } }; $( $tail )* )
26+
$crate::parse!( sol $apply, $ctx, $val; { day $day { { gen_fallible $generator } { } } }; $( $tail )* )
1927
};
2028

2129
// Empty rules

src/run.rs

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ macro_rules! run_day {
44
{ $i: expr, $curr_day: expr, $year: expr, $opt: expr },
55
{ day $day: ident { $gen: tt { $( { sol $solution: ident } )* } } }
66
) => {{
7+
use $crate::colored::*;
8+
79
if stringify!($day) == $curr_day {
810
if $i != 0 { println!() }
911
let day = $curr_day[3..].parse().expect("days must be integers");
@@ -23,19 +25,27 @@ macro_rules! run_day {
2325
}
2426
};
2527

26-
let input = $crate::run_gen!($day, &data, $gen);
27-
28-
$({
29-
let start = Instant::now();
30-
let response = $day::$solution(&input);
31-
let elapsed = start.elapsed();
28+
if let Some(input) = $crate::run_gen!($day, &data, $gen) {
29+
$({
30+
let start = Instant::now();
31+
let response = $day::$solution(&input);
32+
let elapsed = start.elapsed();
3233

33-
$crate::print_with_duration(
34-
stringify!($solution),
35-
Some(&format!("{}", response)),
36-
elapsed,
37-
);
38-
})+
34+
$crate::print_with_duration(
35+
stringify!($solution),
36+
Some(format!("{}", response).normal()),
37+
Some(elapsed),
38+
);
39+
})+
40+
} else {
41+
$({
42+
$crate::print_with_duration(
43+
stringify!($solution),
44+
Some("skipped".dimmed()),
45+
None,
46+
);
47+
})+
48+
}
3949
}
4050
}}
4151
}
@@ -44,15 +54,36 @@ macro_rules! run_day {
4454
macro_rules! run_gen {
4555
// No generator is needed: default begavior is to just pass input &str
4656
( $day: ident, $data: expr, { gen_default } ) => {{
47-
$data
57+
Some($data)
4858
}};
4959

5060
// Run generator
5161
( $day: ident, $data: expr, { gen $generator: ident } ) => {{
5262
let start = Instant::now();
5363
let input = $day::$generator($data);
5464
let elapsed = start.elapsed();
55-
$crate::print_with_duration("generator", None, elapsed);
56-
input
65+
$crate::print_with_duration("generator", None, Some(elapsed));
66+
Some(input)
67+
}};
68+
69+
// Run fallible generator
70+
( $day: ident, $data: expr, { gen_fallible $generator: ident } ) => {{
71+
use $crate::colored::*;
72+
use $crate::try_unwrap::TryUnwrap;
73+
74+
let start = Instant::now();
75+
let result = $day::$generator($data);
76+
let elapsed = start.elapsed();
77+
78+
match result.try_unwrap() {
79+
Ok(input) => {
80+
$crate::print_with_duration("generator", None, Some(elapsed));
81+
Some(input)
82+
}
83+
Err(msg) => {
84+
$crate::print_with_duration("generator", Some(msg.red()), Some(elapsed));
85+
None
86+
}
87+
}
5788
}};
5889
}

src/try_unwrap.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::fmt::Display;
2+
3+
pub trait TryUnwrap {
4+
type Val;
5+
fn try_unwrap(self) -> Result<Self::Val, String>;
6+
}
7+
8+
impl<T> TryUnwrap for Option<T> {
9+
type Val = T;
10+
11+
fn try_unwrap(self) -> Result<Self::Val, String> {
12+
if let Some(val) = self {
13+
Ok(val)
14+
} else {
15+
Err("empty output".to_string())
16+
}
17+
}
18+
}
19+
20+
impl<T, E: Display> TryUnwrap for Result<T, E> {
21+
type Val = T;
22+
23+
fn try_unwrap(self) -> Result<Self::Val, String> {
24+
self.map_err(|err| format!("{}", err))
25+
}
26+
}

0 commit comments

Comments
 (0)