Skip to content

Commit 3786069

Browse files
committed
2017 day 12
1 parent 28fbf14 commit 3786069

File tree

8 files changed

+389
-17
lines changed

8 files changed

+389
-17
lines changed

crates/utils/src/array.rs

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
//! Array helpers.
2+
3+
use std::fmt;
4+
use std::hash::Hash;
5+
use std::ops::{Deref, DerefMut};
6+
7+
/// A fixed-size array-backed vector.
8+
///
9+
/// `ArrayVec` has a fixed-sized `N` long array and a length field to track how many elements are
10+
/// populated. It is useful for storing a small but variable number of elements without heap
11+
/// allocation.
12+
///
13+
/// The implementation is intentionally simple, and requires [`Copy`] and [`Default`] bounds on some
14+
/// methods instead of using [`std::mem::MaybeUninit`].
15+
#[derive(Clone, PartialEq, Eq, Hash)]
16+
pub struct ArrayVec<T, const N: usize> {
17+
len: usize,
18+
data: [T; N],
19+
}
20+
21+
impl<T, const N: usize> ArrayVec<T, N> {
22+
/// Creates a new empty `ArrayVec`.
23+
///
24+
/// # Examples
25+
/// ```
26+
/// # use utils::array::ArrayVec;
27+
/// let vec: ArrayVec<i32, 5> = ArrayVec::new();
28+
/// assert_eq!(vec.len(), 0);
29+
/// ```
30+
#[inline]
31+
#[must_use]
32+
pub fn new() -> Self
33+
where
34+
T: Copy + Default,
35+
{
36+
Self {
37+
len: 0,
38+
data: [T::default(); N],
39+
}
40+
}
41+
42+
/// Adds an element to the end of the vector.
43+
///
44+
/// Returns [`Err`] containing the provided value if the vector is already full.
45+
///
46+
/// # Examples
47+
/// ```
48+
/// # use utils::array::ArrayVec;
49+
/// let mut vec: ArrayVec<i32, 2> = ArrayVec::new();
50+
/// assert_eq!(vec.push(1), Ok(()));
51+
/// assert_eq!(vec.push(2), Ok(()));
52+
/// assert_eq!(vec.push(3), Err(3)); // Vector is full
53+
/// ```
54+
#[inline]
55+
pub fn push(&mut self, value: T) -> Result<(), T> {
56+
if self.len < N {
57+
self.data[self.len] = value;
58+
self.len += 1;
59+
Ok(())
60+
} else {
61+
Err(value)
62+
}
63+
}
64+
65+
/// Removes the last element from the vector and returns it, or [`None`] if it is empty.
66+
///
67+
/// # Examples
68+
/// ```
69+
/// # use utils::array::ArrayVec;
70+
/// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
71+
/// vec.push(1).unwrap();
72+
/// assert_eq!(vec.pop(), Some(1));
73+
/// assert_eq!(vec.pop(), None);
74+
/// ```
75+
#[inline]
76+
pub fn pop(&mut self) -> Option<T>
77+
where
78+
T: Default,
79+
{
80+
if self.len > 0 {
81+
self.len -= 1;
82+
Some(std::mem::take(&mut self.data[self.len]))
83+
} else {
84+
None
85+
}
86+
}
87+
88+
/// Returns a slice of all the populated elements in the vector.
89+
///
90+
/// # Examples
91+
///
92+
/// ```
93+
/// # use utils::array::ArrayVec;
94+
/// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
95+
/// vec.push(1).unwrap();
96+
/// vec.push(2).unwrap();
97+
/// assert_eq!(vec.as_slice(), &[1, 2]);
98+
/// ```
99+
#[inline]
100+
pub fn as_slice(&self) -> &[T] {
101+
#[cfg(feature = "unsafe")]
102+
unsafe {
103+
std::hint::assert_unchecked(self.len <= N);
104+
}
105+
106+
&self.data[..self.len]
107+
}
108+
109+
/// Returns a mutable slice of all the populated elements in the vector.
110+
///
111+
/// # Examples
112+
///
113+
/// ```
114+
/// # use utils::array::ArrayVec;
115+
/// let mut vec: ArrayVec<i32, 3> = ArrayVec::new();
116+
/// vec.push(1).unwrap();
117+
/// vec.push(2).unwrap();
118+
/// let mut slice = vec.as_mut_slice();
119+
/// slice[1] = 10;
120+
/// assert_eq!(slice, &[1, 10]);
121+
/// ```
122+
#[inline]
123+
pub fn as_mut_slice(&mut self) -> &mut [T] {
124+
#[cfg(feature = "unsafe")]
125+
unsafe {
126+
std::hint::assert_unchecked(self.len <= N);
127+
}
128+
129+
&mut self.data[..self.len]
130+
}
131+
132+
/// Returns the capacity of the vector, which is always `N`.
133+
///
134+
/// # Examples
135+
/// ```
136+
/// # use utils::array::ArrayVec;
137+
/// let vec: ArrayVec<i32, 5> = ArrayVec::new();
138+
/// assert_eq!(vec.capacity(), 5);
139+
/// ```
140+
#[inline]
141+
pub fn capacity(&self) -> usize {
142+
N
143+
}
144+
145+
/// Returns whether the vector is full.
146+
///
147+
/// # Examples
148+
///
149+
/// ```
150+
/// # use utils::array::ArrayVec;
151+
/// let mut vec: ArrayVec<i32, 2> = ArrayVec::new();
152+
/// assert!(!vec.is_full());
153+
/// vec.push(1).unwrap();
154+
/// assert!(!vec.is_full());
155+
/// vec.push(2).unwrap();
156+
/// assert!(vec.is_full());
157+
/// ```
158+
#[inline]
159+
pub fn is_full(&self) -> bool {
160+
self.len == N
161+
}
162+
}
163+
164+
impl<T, const N: usize> Deref for ArrayVec<T, N> {
165+
type Target = [T];
166+
167+
#[inline]
168+
fn deref(&self) -> &Self::Target {
169+
self.as_slice()
170+
}
171+
}
172+
173+
impl<T, const N: usize> DerefMut for ArrayVec<T, N> {
174+
#[inline]
175+
fn deref_mut(&mut self) -> &mut Self::Target {
176+
self.as_mut_slice()
177+
}
178+
}
179+
180+
impl<'a, T, const N: usize> IntoIterator for &'a ArrayVec<T, N> {
181+
type Item = &'a T;
182+
type IntoIter = std::slice::Iter<'a, T>;
183+
184+
#[inline]
185+
fn into_iter(self) -> Self::IntoIter {
186+
self.iter()
187+
}
188+
}
189+
190+
impl<'a, T, const N: usize> IntoIterator for &'a mut ArrayVec<T, N> {
191+
type Item = &'a mut T;
192+
type IntoIter = std::slice::IterMut<'a, T>;
193+
194+
#[inline]
195+
fn into_iter(self) -> Self::IntoIter {
196+
self.iter_mut()
197+
}
198+
}
199+
200+
impl<T: fmt::Debug, const N: usize> fmt::Debug for ArrayVec<T, N> {
201+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202+
f.debug_struct("ArrayVec")
203+
.field("len", &self.len)
204+
.field("cap", &N)
205+
.field("data", &self.as_slice())
206+
.finish()
207+
}
208+
}
209+
210+
impl<T: Default + Copy, const N: usize> Default for ArrayVec<T, N> {
211+
fn default() -> Self {
212+
Self::new()
213+
}
214+
}

crates/utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Common utilities used by the [`aoc`](../aoc/) and year crates.
22
#![cfg_attr(not(feature = "unsafe"), forbid(unsafe_code))]
33

4+
pub mod array;
45
pub mod bit;
56
pub mod date;
67
mod framework;

crates/utils/src/parser/base.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::input::{InputError, MapWithInputExt};
22
use crate::parser::combinator::{
3-
Map, MapResult, Optional, Or, RepeatN, RepeatVec, WithPrefix, WithSuffix,
3+
Map, MapResult, Optional, Or, RepeatArrayVec, RepeatN, RepeatVec, WithPrefix, WithSuffix,
44
};
55
use crate::parser::error::WithErrorMsg;
66
use crate::parser::simple::{Constant, Eol};
@@ -156,8 +156,8 @@ pub trait Parser: Sized {
156156

157157
/// Repeat this parser `N` times, returning an [`array`].
158158
///
159-
/// See also [`repeat`](Self::repeat) which returns a [`Vec`] instead, for unknown or varying
160-
/// number of repeats.
159+
/// If the number of items is variable use [`repeat_arrayvec`](Self::repeat_arrayvec) or
160+
/// [`repeat`](Self::repeat).
161161
///
162162
/// # Examples
163163
/// ```
@@ -177,10 +177,41 @@ pub trait Parser: Sized {
177177
RepeatN { parser: self }
178178
}
179179

180+
/// Repeat this parser while it matches, returning a [`ArrayVec`](crate::array::ArrayVec).
181+
///
182+
/// This parser can parse up to `N` items. If more items match, it will return an error.
183+
///
184+
/// See [`repeat`](Self::repeat) if the upper bound is large or not known, and
185+
/// [`repeat_n`](Self::repeat_n) if the number of items is consistent.
186+
///
187+
/// # Examples
188+
/// ```
189+
/// # use utils::parser::{self, Parser};
190+
/// let parser = parser::u32()
191+
/// .repeat(",", 3);
192+
/// assert_eq!(parser.parse(b"12,34,56,78"), Ok((vec![12, 34, 56, 78], &b""[..])));
193+
/// assert!(parser.parse(b"12,34").is_err());
194+
/// ```
195+
fn repeat_arrayvec<const N: usize, S: Parser>(
196+
self,
197+
separator: S,
198+
min_elements: usize,
199+
) -> RepeatArrayVec<N, Self, S>
200+
where
201+
for<'a> Self::Output<'a>: Copy + Default,
202+
{
203+
RepeatArrayVec {
204+
parser: self,
205+
separator,
206+
min_elements,
207+
}
208+
}
209+
180210
/// Repeat this parser while it matches, returning a [`Vec`].
181211
///
182-
/// If the number of items is constant and known in advance, prefer [`repeat_n`](Self::repeat_n)
183-
/// as it avoids allocating.
212+
/// To avoid allocating, prefer [`repeat_n`](Self::repeat_n) if the number of items is
213+
/// consistent and known in advance, or [`repeat_arrayvec`](Self::repeat_arrayvec) if the number
214+
/// of items is variable but has a known upper bound.
184215
///
185216
/// # Examples
186217
/// ```
@@ -356,8 +387,10 @@ impl Parser for &'static str {
356387

357388
#[inline]
358389
fn parse<'i>(&self, input: &'i [u8]) -> ParseResult<'i, Self::Output<'i>> {
359-
if let Some(remainder) = input.strip_prefix(self.as_bytes()) {
360-
Ok((self, remainder))
390+
// This is faster than using strip_prefix for the common case where the string is a short
391+
// string literal known at compile time.
392+
if input.len() >= self.len() && self.bytes().zip(input).all(|(a, &b)| a == b) {
393+
Ok((self, &input[self.len()..]))
361394
} else {
362395
Err((ParseError::ExpectedLiteral(self), input))
363396
}

0 commit comments

Comments
 (0)