aoc/
input.rs

1use std::{fmt, iter, ops::Index, slice};
2
3/// A struct for handling and parsing an input for an Advent of Code problem.
4#[derive(Clone, Copy, Debug)]
5pub struct Input<'a> {
6    raw: &'a str,
7    lines: &'a [&'a str],
8}
9
10impl<'a> Input<'a> {
11    pub(crate) fn new(raw: &'a str, lines: &'a [&'a str]) -> Self {
12        Self { raw, lines }
13    }
14
15    /// Returns the raw input `&str`.
16    #[inline(always)]
17    pub fn raw(self) -> &'a str {
18        self.raw
19    }
20
21    /// Returns an iterator over the lines of the input.
22    ///
23    /// Alias for `.into_iter()`.
24    #[inline(always)]
25    pub fn lines(self) -> Lines<'a> {
26        self.into_iter()
27    }
28
29    /// Returns the lines of the input as a slice.
30    #[inline(always)]
31    pub fn as_lines(self) -> &'a [&'a str] {
32        self.lines
33    }
34
35    /// Returns the number of lines in the input.
36    #[inline(always)]
37    #[allow(clippy::len_without_is_empty)] // Panics if the input is empty.
38    pub fn len(self) -> usize {
39        self.lines.len()
40    }
41}
42
43/// An iterator over the lines of an `Input`.
44#[derive(Clone)]
45pub struct Lines<'a> {
46    inner: slice::Iter<'a, &'a str>,
47}
48
49impl<'a> Iterator for Lines<'a> {
50    type Item = &'a str;
51
52    #[inline]
53    fn next(&mut self) -> Option<Self::Item> {
54        self.inner.next().copied()
55    }
56}
57
58impl<'a> DoubleEndedIterator for Lines<'a> {
59    fn next_back(&mut self) -> Option<Self::Item> {
60        self.inner.next_back().copied()
61    }
62}
63
64impl<'a> ExactSizeIterator for Lines<'a> {
65    fn len(&self) -> usize {
66        self.inner.len()
67    }
68}
69
70impl<'a> iter::FusedIterator for Lines<'a> {}
71
72impl<'a> IntoIterator for Input<'a> {
73    type Item = &'a str;
74    type IntoIter = Lines<'a>;
75
76    #[inline]
77    fn into_iter(self) -> Self::IntoIter {
78        Lines {
79            inner: self.lines.iter(),
80        }
81    }
82}
83
84impl<'a, T> Index<T> for Input<'a>
85where
86    [&'a str]: Index<T>,
87{
88    type Output = <[&'a str] as Index<T>>::Output;
89
90    #[inline]
91    #[track_caller]
92    fn index(&self, index: T) -> &Self::Output {
93        &self.lines[index]
94    }
95}
96
97impl<'a> fmt::Display for Input<'a> {
98    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99        <str as fmt::Display>::fmt(self.raw, f)
100    }
101}