aoc_runner_internal/
lib.rs

1extern crate serde;
2extern crate serde_derive;
3extern crate serde_json;
4
5use serde_derive::*;
6use std::cmp::Ordering;
7use std::error;
8use std::fs;
9use std::iter::FromIterator;
10use std::ops::Deref;
11use std::ops::DerefMut;
12use std::str::FromStr;
13
14#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone, Serialize, Deserialize, Ord, PartialOrd)]
15pub struct Day(pub u8);
16
17impl FromStr for Day {
18    type Err = String;
19
20    fn from_str(day: &str) -> Result<Self, Self::Err> {
21        let slice = if day.len() < 4 || &day[..3] != "day" {
22            &day[..]
23        } else {
24            &day[3..]
25        };
26
27        slice
28            .parse()
29            .map_err(|e| format!("Failed to parse {}: {:?}", day, e))
30            .and_then(|d| {
31                if d == 0 || d > 25 {
32                    Err(format!("day {} is not between 0 and 25", d))
33                } else {
34                    Ok(Day(d))
35                }
36            })
37    }
38}
39
40#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone, Serialize, Deserialize, Ord, PartialOrd)]
41pub struct Part(pub u8);
42
43impl FromStr for Part {
44    type Err = String;
45
46    fn from_str(part: &str) -> Result<Self, Self::Err> {
47        Ok(match part {
48            "part1" | "1" => Part(1),
49            "part2" | "2" => Part(2),
50            _ => return Err(format!("Failed to parse part: {}", part)),
51        })
52    }
53}
54
55#[derive(Debug, Hash, Eq, PartialEq, Clone, Serialize, Deserialize)]
56pub struct DayPart {
57    pub day: Day,
58    pub part: Part,
59    pub name: Option<String>,
60}
61
62impl DayPart {
63    pub fn without_name(&self) -> DayPart {
64        DayPart {
65            name: None,
66            day: self.day,
67            part: self.part,
68        }
69    }
70}
71
72impl PartialOrd for DayPart {
73    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
74        Some(self.cmp(&other))
75    }
76}
77
78impl Ord for DayPart {
79    fn cmp(&self, other: &Self) -> Ordering {
80        self.day
81            .cmp(&other.day)
82            .then(self.part.cmp(&other.part))
83            .then(self.name.cmp(&other.name))
84    }
85}
86
87#[derive(Serialize, Deserialize, Debug)]
88pub struct DayParts {
89    pub year: u32,
90    parts: Vec<DayPart>,
91}
92
93impl DayParts {
94    pub fn save(&self) -> Result<(), Box<error::Error>> {
95        fs::create_dir_all("target/aoc")?;
96        let f = fs::File::create("target/aoc/completed.json")?;
97
98        serde_json::to_writer_pretty(f, &self)?;
99
100        Ok(())
101    }
102
103    pub fn load() -> Result<Self, Box<error::Error>> {
104        let f = fs::File::open("target/aoc/completed.json")?;
105
106        Ok(serde_json::from_reader(f)?)
107    }
108}
109
110impl Deref for DayParts {
111    type Target = [DayPart];
112
113    fn deref(&self) -> &[DayPart] {
114        &self.parts
115    }
116}
117
118impl DerefMut for DayParts {
119    fn deref_mut(&mut self) -> &mut [DayPart] {
120        &mut self.parts
121    }
122}
123
124pub struct DayPartsBuilder {
125    parts: Vec<DayPart>,
126}
127
128impl DayPartsBuilder {
129    pub fn with_year(self, year: u32) -> DayParts {
130        DayParts {
131            year,
132            parts: self.parts,
133        }
134    }
135}
136
137impl FromIterator<DayPart> for DayPartsBuilder {
138    fn from_iter<T: IntoIterator<Item = DayPart>>(iter: T) -> Self {
139        let parts = iter.into_iter().collect();
140        DayPartsBuilder { parts }
141    }
142}