1+ pub mod input;
2+
13use std:: cmp:: min;
2- use std:: error:: Error ;
3- use std:: fs:: { create_dir_all, read_to_string, File } ;
4- use std:: io:: Write ;
5- use std:: io:: { stdin, stdout} ;
64use std:: iter;
7- use std:: path:: PathBuf ;
8- use std:: time:: { Duration , Instant } ;
5+ use std:: time:: Duration ;
96
107pub use clap:: Clap ;
118pub use colored;
129use colored:: * ;
1310
1411const DISPLAY_WIDTH : usize = 40 ;
15- const BASE_URL : & str = "https://adventofcode.com" ;
16- const INPUT_DIR : & str = "input" ;
17- const CONN_TOKEN_FILE : & str = ".token" ;
18-
19- #[ derive( Debug , Clap ) ]
20- #[ clap(
21- name = "Advent of Code" ,
22- about = concat!( "Main page of the event: https://adventofcode.com/" )
23- ) ]
24- pub struct Opt {
25- /// Read input from stdin instead of downloading it
26- #[ clap( short, long) ]
27- pub stdin : bool ,
28-
29- /// Days to execute. By default all implemented days will run.
30- #[ clap( short, long) ]
31- pub days : Vec < String > ,
32- }
3312
3413pub fn print_with_duration ( line : & str , output : Option < & str > , duration : Duration ) {
3514 let duration = format ! ( "({:.2?})" , duration) ;
@@ -55,62 +34,19 @@ pub fn print_with_duration(line: &str, output: Option<&str>, duration: Duration)
5534 }
5635}
5736
58- fn input_path ( year : u16 , day : u8 ) -> String {
59- format ! ( "{}/{}/day{}.txt" , INPUT_DIR , year, day)
60- }
61-
62- fn get_from_path_or_else < E : Error > (
63- path : & str ,
64- fallback : impl FnOnce ( ) -> Result < String , E > ,
65- ) -> Result < String , E > {
66- let from_path = read_to_string ( path) ;
67-
68- if let Ok ( res) = from_path {
69- Ok ( res. trim ( ) . to_string ( ) )
70- } else {
71- let res = fallback ( ) ?;
72- create_dir_all ( PathBuf :: from ( path) . parent ( ) . unwrap ( ) )
73- . and_then ( |_| File :: create ( path) )
74- . and_then ( |mut file| file. write_all ( res. as_bytes ( ) ) )
75- . unwrap_or_else ( |err| eprintln ! ( "could not write {}: {}" , path, err) ) ;
76- Ok ( res)
77- }
78- }
79-
80- pub fn get_input ( year : u16 , day : u8 ) -> Result < String , Box < dyn Error > > {
81- let mut result = get_from_path_or_else ( & input_path ( year, day) , || {
82- let start = Instant :: now ( ) ;
83- let url = format ! ( "{}/{}/day/{}/input" , BASE_URL , year, day) ;
84- let session_cookie = format ! ( "session={}" , get_conn_token( ) ?) ;
85- let resp = attohttpc:: get ( & url)
86- . header ( attohttpc:: header:: COOKIE , session_cookie)
87- . send ( ) ?;
88- let elapsed = start. elapsed ( ) ;
89-
90- print_with_duration ( "downloaded input file" , None , elapsed) ;
91- resp. text ( )
92- } ) ?;
93-
94- if result. ends_with ( '\n' ) {
95- result. pop ( ) ;
96- }
97-
98- Ok ( result)
99- }
100-
101- pub fn get_conn_token ( ) -> Result < String , std:: io:: Error > {
102- get_from_path_or_else ( CONN_TOKEN_FILE , || {
103- let mut stdout = stdout ( ) ;
104- write ! ( & mut stdout, "Write your connection token: " ) ?;
105- stdout. flush ( ) ?;
106-
107- let mut output = String :: new ( ) ;
108- stdin ( ) . read_line ( & mut output) ?;
37+ #[ derive( Debug , Clap ) ]
38+ #[ clap(
39+ name = "Advent of Code" ,
40+ about = concat!( "Main page of the event: https://adventofcode.com/" )
41+ ) ]
42+ pub struct Opt {
43+ /// Read input from stdin instead of downloading it
44+ #[ clap( short, long) ]
45+ pub stdin : bool ,
10946
110- let mut file = File :: create ( CONN_TOKEN_FILE ) ?;
111- file. write_all ( output. as_bytes ( ) ) ?;
112- Ok ( output. trim ( ) . to_string ( ) )
113- } )
47+ /// Days to execute. By default all implemented days will run.
48+ #[ clap( short, long) ]
49+ pub days : Vec < String > ,
11450}
11551
11652#[ macro_export]
@@ -135,51 +71,57 @@ macro_rules! main {
13571 opt. days = DAYS . iter( ) . map( |s| s[ 3 ..] . to_string( ) ) . collect( ) ;
13672 }
13773
138- for ( i, day) in opt. days. iter( ) . enumerate( ) { $ ( {
74+ for ( i, day) in opt. days. iter( ) . enumerate( ) {
13975 let module_name = format!( "day{}" , day) ;
14076 let day = day. parse( ) . expect( "days must be integers" ) ;
14177
14278 if !DAYS . contains( & module_name. as_str( ) ) {
143- eprintln!( "Module `{}` was not registered" , module_name) ;
79+ eprintln!(
80+ "Module `{}` was not registered, available are: {}" ,
81+ module_name,
82+ DAYS . join( ", " ) ,
83+ ) ;
14484 }
14585
146- if stringify!( $day) == module_name {
147- if i != 0 { println!( ) }
148- println!( "Day {}" , day) ;
149-
150- let data = {
151- if opt. stdin {
152- let mut data = String :: new( ) ;
153- std:: io:: stdin( ) . read_to_string( & mut data)
154- . expect( "failed to read from stdin" ) ;
155- data
156- } else {
157- $crate:: get_input( YEAR , day) . expect( "could not fetch input" )
158- }
159- } ;
160-
161- let input = data. as_str( ) ;
162-
163- $(
164- let start = Instant :: now( ) ;
165- let input = $day:: $generator( & data) ;
166- let elapsed = start. elapsed( ) ;
167- $crate:: print_with_duration( "generator" , None , elapsed) ;
168- ) ?
169-
170- $( {
171- let start = Instant :: now( ) ;
172- let response = $day:: $solution( & input) ;
173- let elapsed = start. elapsed( ) ;
174-
175- $crate:: print_with_duration(
176- stringify!( $solution) ,
177- Some ( & format!( "{}" , response) ) ,
178- elapsed,
179- ) ;
180- } ) +
181- }
182- } ) +}
86+ $(
87+ if stringify!( $day) == module_name {
88+ if i != 0 { println!( ) }
89+ println!( "Day {}" , day) ;
90+
91+ let data = {
92+ if opt. stdin {
93+ let mut data = String :: new( ) ;
94+ std:: io:: stdin( ) . read_to_string( & mut data)
95+ . expect( "failed to read from stdin" ) ;
96+ data
97+ } else {
98+ $crate:: input:: get_input( YEAR , day) . expect( "could not fetch input" )
99+ }
100+ } ;
101+
102+ let input = data. as_str( ) ;
103+
104+ $(
105+ let start = Instant :: now( ) ;
106+ let input = $day:: $generator( & data) ;
107+ let elapsed = start. elapsed( ) ;
108+ $crate:: print_with_duration( "generator" , None , elapsed) ;
109+ ) ?
110+
111+ $( {
112+ let start = Instant :: now( ) ;
113+ let response = $day:: $solution( & input) ;
114+ let elapsed = start. elapsed( ) ;
115+
116+ $crate:: print_with_duration(
117+ stringify!( $solution) ,
118+ Some ( & format!( "{}" , response) ) ,
119+ elapsed,
120+ ) ;
121+ } ) +
122+ }
123+ ) +
124+ }
183125 }
184126 } ;
185127}
0 commit comments