advent_of_code_data/
lib.rs1#![doc = include_str!("../README.md")]
2use std::str::FromStr;
3
4use client::{Client, ClientError, WebClient};
5use data::CheckResult;
6
7pub mod cache;
8pub mod client;
9pub mod config;
10pub mod data;
11
12mod utils;
13
14#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
17pub struct Day(pub usize);
18
19impl std::fmt::Display for Day {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "{}", self.0)
22 }
23}
24
25impl From<i32> for Day {
26 fn from(value: i32) -> Self {
27 assert!(value >= 0);
28 Day(value as usize)
29 }
30}
31
32impl From<u32> for Day {
33 fn from(value: u32) -> Self {
34 Day(value as usize)
35 }
36}
37
38#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
41pub struct Year(pub usize);
42
43impl std::fmt::Display for Year {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}", self.0)
46 }
47}
48
49impl From<i32> for Year {
50 fn from(value: i32) -> Self {
51 assert!(value >= 0);
52 Year(value as usize)
53 }
54}
55
56impl From<Year> for i32 {
57 fn from(value: Year) -> Self {
58 value.0 as i32
59 }
60}
61
62#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
65pub enum Part {
66 One,
67 Two,
68}
69
70impl std::fmt::Display for Part {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 write!(
73 f,
74 "{}",
75 match self {
76 Part::One => "One",
77 Part::Two => "Two",
78 }
79 )
80 }
81}
82
83#[derive(Clone, Debug, PartialEq)]
122pub enum Answer {
123 String(String),
124 Int(i128),
125}
126
127impl Answer {
128 pub fn to_i128(&self) -> Option<i128> {
129 match self {
130 Answer::String(_) => None,
131 Answer::Int(v) => Some(*v),
132 }
133 }
134}
135
136impl FromStr for Answer {
137 type Err = ();
138
139 fn from_str(s: &str) -> Result<Self, Self::Err> {
140 Ok(s.parse::<i128>()
141 .map_or_else(|_| Answer::String(s.to_string()), Answer::Int))
142 }
143}
144
145impl std::fmt::Display for Answer {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 match self {
148 Answer::String(v) => write!(f, "{}", v),
149 Answer::Int(v) => write!(f, "{}", v),
150 }
151 }
152}
153
154impl From<String> for Answer {
155 fn from(value: String) -> Self {
156 Self::String(value)
157 }
158}
159
160impl From<&str> for Answer {
161 fn from(value: &str) -> Self {
162 Self::String(value.to_string())
163 }
164}
165
166impl From<i8> for Answer {
167 fn from(value: i8) -> Self {
168 Self::Int(value as i128)
169 }
170}
171
172impl From<i16> for Answer {
173 fn from(value: i16) -> Self {
174 Self::Int(value as i128)
175 }
176}
177
178impl From<i32> for Answer {
179 fn from(value: i32) -> Self {
180 Self::Int(value as i128)
181 }
182}
183
184impl From<i64> for Answer {
185 fn from(value: i64) -> Self {
186 Self::Int(value as i128)
187 }
188}
189impl From<u8> for Answer {
190 fn from(value: u8) -> Self {
191 Self::Int(value as i128)
192 }
193}
194
195impl From<u16> for Answer {
196 fn from(value: u16) -> Self {
197 Self::Int(value as i128)
198 }
199}
200
201impl From<u32> for Answer {
202 fn from(value: u32) -> Self {
203 Self::Int(value as i128)
204 }
205}
206
207impl From<u64> for Answer {
208 fn from(value: u64) -> Self {
209 Self::Int(value as i128)
210 }
211}
212
213impl From<isize> for Answer {
214 fn from(value: isize) -> Self {
215 Self::Int(value as i128)
216 }
217}
218
219impl From<usize> for Answer {
220 fn from(value: usize) -> Self {
221 Self::Int(value as i128)
222 }
223}
224
225pub fn get_input(day: Day, year: Year) -> Result<String, ClientError> {
227 let client = WebClient::new()?;
228 client.get_input(day, year)
229}
230
231pub fn submit_answer(
233 answer: Answer,
234 part: Part,
235 day: Day,
236 year: Year,
237) -> Result<CheckResult, ClientError> {
238 let mut client: WebClient = WebClient::new()?;
239 client.submit_answer(answer, part, day, year)
240}
241
242#[cfg(test)]
243mod tests {
244 use super::*;
245
246 #[test]
247 fn print_year() {
248 let year = Year(2022);
249 assert_eq!(&format!("{year}"), "2022");
250 }
251
252 #[test]
253 fn print_day() {
254 let day = Day(22);
255 assert_eq!(&format!("{day}"), "22");
256 }
257
258 #[test]
259 fn print_part() {
260 assert_eq!(&format!("{}", Part::One), "One");
261 assert_eq!(&format!("{}", Part::Two), "Two");
262 }
263
264 #[test]
265 fn print_answer() {
266 assert_eq!(
267 &format!("{}", Answer::String("hello world".to_string())),
268 "hello world"
269 );
270
271 assert_eq!(&format!("{}", Answer::Int(42)), "42");
272 }
273
274 #[test]
275 #[allow(clippy::unnecessary_cast)]
276 fn int_answer_conversions() {
277 let answer: Answer = (-22 as i8).into();
278 assert_eq!(answer, Answer::Int(-22));
279
280 let answer: Answer = (-1317 as i16).into();
281 assert_eq!(answer, Answer::Int(-1317));
282
283 let answer: Answer = (-100_512 as i32).into();
284 assert_eq!(answer, Answer::Int(-100_512));
285
286 let answer: Answer = (-3_183_512_681 as i64).into();
287 assert_eq!(answer, Answer::Int(-3_183_512_681));
288
289 let answer: Answer = (22 as u8).into();
290 assert_eq!(answer, Answer::Int(22));
291
292 let answer: Answer = (1317 as u16).into();
293 assert_eq!(answer, Answer::Int(1317));
294
295 let answer: Answer = (100_512 as u32).into();
296 assert_eq!(answer, Answer::Int(100_512));
297
298 let answer: Answer = (3_183_512_681 as u64).into();
299 assert_eq!(answer, Answer::Int(3_183_512_681));
300 }
301
302 #[test]
303 fn string_answer_conversions() {
304 let answer: Answer = "hello world".to_string().into();
305 assert_eq!(answer, Answer::String("hello world".to_string()));
306
307 let answer: Answer = "testing 123".into();
308 assert_eq!(answer, Answer::String("testing 123".to_string()));
309 }
310
311 #[test]
312 fn parse_string_to_answer() {
313 let answer: Answer = "this is text".parse::<Answer>().unwrap();
314 assert_eq!(answer, Answer::String("this is text".to_string()));
315
316 let answer: Answer = "123".parse::<Answer>().unwrap();
317 assert_eq!(answer, Answer::Int(123));
318 }
319}