advent_of_code_data/
lib.rs

1use 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}