advent_of_code_data/
lib.rs1use std::str::FromStr;
2
3use client::WebClient;
4use data::CheckResult;
5use thiserror::Error;
6
7pub mod cache;
8pub mod client;
9pub mod data;
10pub mod registry;
11pub mod settings;
12pub mod utils;
13
14#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
15pub struct Day(pub usize);
16
17impl std::fmt::Display for Day {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 write!(f, "{}", self.0)
20 }
21}
22
23impl From<i32> for Day {
24 fn from(value: i32) -> Self {
25 assert!(value >= 0);
26 Day(value as usize)
27 }
28}
29
30impl From<u32> for Day {
31 fn from(value: u32) -> Self {
32 Day(value as usize)
33 }
34}
35
36#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
37pub struct Year(pub usize);
38
39impl std::fmt::Display for Year {
40 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41 write!(f, "{}", self.0)
42 }
43}
44
45impl From<i32> for Year {
46 fn from(value: i32) -> Self {
47 assert!(value >= 0);
48 Year(value as usize)
49 }
50}
51
52impl From<Year> for i32 {
53 fn from(value: Year) -> Self {
54 value.0 as i32
55 }
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
59pub enum Part {
60 One,
61 Two,
62}
63
64impl std::fmt::Display for Part {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 write!(
67 f,
68 "{}",
69 match self {
70 Part::One => "One",
71 Part::Two => "Two",
72 }
73 )
74 }
75}
76
77#[derive(Clone, Debug, PartialEq, Error)]
78pub enum AnswerParseError {
79 #[error("answers with empty strings or only whitespace chars are not allowed")]
80 EmptyNotAllowed,
81 #[error("answers with newline characters are not allowed")]
82 NewlinesNotAllowed,
83}
84
85#[derive(Clone, Debug, PartialEq)]
86pub enum Answer {
87 String(String),
88 Int(i64),
89}
90
91impl Answer {
92 pub fn to_i64(&self) -> Option<i64> {
93 match self {
94 Answer::String(_) => None,
95 Answer::Int(v) => Some(*v),
96 }
97 }
98}
99
100impl FromStr for Answer {
101 type Err = AnswerParseError;
102
103 fn from_str(s: &str) -> Result<Self, Self::Err> {
104 if s.is_empty() || s.chars().all(|c| c.is_whitespace()) {
105 return Err(AnswerParseError::EmptyNotAllowed);
106 }
107
108 if s.chars().any(|c| c == '\n') {
109 return Err(AnswerParseError::NewlinesNotAllowed);
110 }
111
112 Ok(s.parse::<i64>()
113 .map_or_else(|_| Answer::String(s.to_string()), Answer::Int))
114 }
115}
116
117impl std::fmt::Display for Answer {
118 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119 match self {
120 Answer::String(v) => write!(f, "{}", v),
121 Answer::Int(v) => write!(f, "{}", v),
122 }
123 }
124}
125
126impl From<String> for Answer {
127 fn from(value: String) -> Self {
128 Self::String(value)
129 }
130}
131
132impl From<i64> for Answer {
133 fn from(value: i64) -> Self {
134 Self::Int(value)
135 }
136}
137
138impl From<i32> for Answer {
139 fn from(value: i32) -> Self {
140 Self::Int(value as i64)
141 }
142}
143
144impl From<isize> for Answer {
145 fn from(value: isize) -> Self {
146 Self::Int(value as i64)
147 }
148}
149
150impl From<usize> for Answer {
151 fn from(value: usize) -> Self {
152 assert!(value as u64 <= i64::MAX as u64);
153 Self::Int(value as i64)
154 }
155}
156
157pub fn get_input(day: Day, year: Year) -> String {
158 let client: WebClient = Default::default();
159 client.get_input(day, year)
160}
161
162pub fn submit_answer(answer: Answer, part: Part, day: Day, year: Year) -> CheckResult {
163 let mut client: WebClient = Default::default();
164 client.submit_answer(answer, part, day, year)
165}