1#![allow(clippy::redundant_pub_crate)]
2#![allow(unused)]
3
4use std::cell::RefCell;
5
6pub type ResultType = String;
7
8#[derive(Copy, Clone)]
9pub enum Part {
10 One,
11 Two,
12}
13
14pub struct Input<'a> {
15 pub part: Part,
16 pub text: &'a str,
17 #[cfg(feature = "visualization")]
18 pub visualization: RefCell<String>,
19}
20
21#[allow(single_use_lifetimes)]
22#[allow(clippy::needless_lifetimes)]
23impl<'a> Input<'a> {
24 pub const fn is_part_one(&self) -> bool {
25 matches!(self.part, Part::One)
26 }
27
28 pub const fn is_part_two(&self) -> bool {
29 matches!(self.part, Part::Two)
30 }
31
32 pub fn part_values<T>(&self, if_part_one: T, if_part_two: T) -> T {
33 #![allow(clippy::missing_const_for_fn)]
35 match self.part {
36 Part::One => if_part_one,
37 Part::Two => if_part_two,
38 }
39 }
40
41 #[cfg(test)]
42 #[allow(clippy::missing_const_for_fn)]
43 pub fn part_one(text: &'a str) -> Self {
44 Self {
45 part: Part::One,
46 text,
47 #[cfg(feature = "visualization")]
48 visualization: RefCell::new("".to_string()),
49 }
50 }
51
52 #[cfg(test)]
53 #[allow(clippy::missing_const_for_fn)]
54 pub fn part_two(text: &'a str) -> Self {
55 Self {
56 part: Part::Two,
57 text,
58 #[cfg(feature = "visualization")]
59 visualization: RefCell::new("".to_string()),
60 }
61 }
62}
63
64#[cfg(test)]
65macro_rules! test_part_one {
66 ($input:tt => $expected:expr) => {
67 assert_eq!(solve(&Input::part_one($input)), Ok($expected));
68 };
69}
70#[cfg(test)]
71pub(crate) use test_part_one;
72
73#[cfg(test)]
74macro_rules! test_part_one_no_allocations {
75 ($input:tt => $expected:expr) => {
76 #[cfg(feature = "count-allocations")]
77 {
78 let info = allocation_counter::measure(|| {
79 assert_eq!(solve(&Input::part_one($input)), Ok($expected));
80 });
81 assert_eq!(0, info.count_total);
82 }
83 #[cfg(not(feature = "count-allocations"))]
84 {
85 assert_eq!(solve(&Input::part_one($input)), Ok($expected));
86 }
87 };
88}
89#[cfg(test)]
90pub(crate) use test_part_one_no_allocations;
91
92#[cfg(test)]
93macro_rules! test_part_two {
94 ($input:tt => $expected:expr) => {
95 assert_eq!(solve(&Input::part_two($input)), Ok($expected));
96 };
97}
98#[cfg(test)]
99pub(crate) use test_part_two;
100
101#[cfg(test)]
102macro_rules! test_part_two_no_allocations {
103 ($input:tt => $expected:expr) => {
104 #[cfg(feature = "count-allocations")]
105 {
106 let info = allocation_counter::measure(|| {
107 assert_eq!(solve(&Input::part_two($input)), Ok($expected));
108 });
109 assert_eq!(0, info.count_total);
110 }
111 #[cfg(not(feature = "count-allocations"))]
112 {
113 assert_eq!(solve(&Input::part_two($input)), Ok($expected));
114 }
115 };
116}
117#[cfg(test)]
118pub(crate) use test_part_two_no_allocations;
119
120#[cfg(test)]
121macro_rules! test_part_one_error {
122 ($input:tt => $expected:expr) => {
123 assert_eq!(Err($expected.into()), solve(&Input::part_one($input)));
124 };
125}
126#[cfg(test)]
127pub(crate) use test_part_one_error;
128
129#[cfg(test)]
130macro_rules! test_part_two_error {
131 ($input:tt => $expected:expr) => {
132 assert_eq!(Err($expected.into()), solve(&Input::part_two($input)));
133 };
134}
135#[cfg(test)]
136pub(crate) use test_part_two_error;
137
138pub fn on_error() -> String {
139 "Invalid input".to_string()
140}