Skip to content

Commit c3d362f

Browse files
committed
Don't parse trailing separator in parser.repeat(_arrayvec)
1 parent cfa95b5 commit c3d362f

File tree

4 files changed

+54
-10
lines changed

4 files changed

+54
-10
lines changed

crates/utils/src/array.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,38 @@ impl<T, const N: usize> ArrayVec<T, N> {
3939
}
4040
}
4141

42+
/// Creates a new `ArrayVec`, copying initial data from the provided slice.
43+
///
44+
/// # Examples
45+
/// ```
46+
/// # use utils::array::ArrayVec;
47+
/// let mut vec: ArrayVec<i32, 5> = ArrayVec::<i32, 5>::from_slice(&[1, 2, 3]).unwrap();
48+
/// assert_eq!(vec.len(), 3);
49+
/// assert_eq!(vec.pop(), Some(3));
50+
/// assert_eq!(vec.pop(), Some(2));
51+
/// assert_eq!(vec.pop(), Some(1));
52+
/// assert_eq!(vec.pop(), None);
53+
///
54+
/// assert_eq!(ArrayVec::<i32, 5>::from_slice(&[1, 2, 3, 4, 5, 6]), None);
55+
/// ```
56+
#[inline]
57+
#[must_use]
58+
pub fn from_slice(slice: &[T]) -> Option<Self>
59+
where
60+
T: Copy + Default,
61+
{
62+
if slice.len() > N {
63+
None
64+
} else {
65+
let mut data = [T::default(); N];
66+
data[..slice.len()].copy_from_slice(slice);
67+
Some(Self {
68+
len: slice.len(),
69+
data,
70+
})
71+
}
72+
}
73+
4274
/// Adds an element to the end of the vector.
4375
///
4476
/// Returns [`Err`] containing the provided value if the vector is already full.

crates/utils/src/parser/base.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,18 @@ pub trait Parser<'i>: Sized {
226226
///
227227
/// # Examples
228228
/// ```
229-
/// # use utils::parser::{self, Parser};
229+
/// # use utils::array::ArrayVec;
230+
/// use utils::parser::{self, Parser};
230231
/// let parser = parser::u32()
231-
/// .repeat_arrayvec(",", 3);
232-
/// assert_eq!(parser.parse(b"12,34,56,78"), Ok(([12, 34, 56, 78].into(), &b""[..])));
232+
/// .repeat_arrayvec::<5, _>(",", 3);
233+
/// assert_eq!(
234+
/// parser.parse(b"12,34,56,78"),
235+
/// Ok((ArrayVec::from_slice(&[12, 34, 56, 78]).unwrap(), &b""[..]))
236+
/// );
237+
/// assert_eq!(
238+
/// parser.parse(b"12,34,56,abc"),
239+
/// Ok((ArrayVec::from_slice(&[12, 34, 56]).unwrap(), &b",abc"[..]))
240+
/// );
233241
/// assert!(parser.parse(b"12,34").is_err());
234242
/// ```
235243
#[inline]
@@ -260,6 +268,7 @@ pub trait Parser<'i>: Sized {
260268
/// let parser = parser::u32()
261269
/// .repeat(",", 3);
262270
/// assert_eq!(parser.parse(b"12,34,56,78"), Ok((vec![12, 34, 56, 78], &b""[..])));
271+
/// assert_eq!(parser.parse(b"12,34,56,abc"), Ok((vec![12, 34, 56], &b",abc"[..])));
263272
/// assert!(parser.parse(b"12,34").is_err());
264273
/// ```
265274
#[inline]

crates/utils/src/parser/combinator.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ impl<'i, const N: usize, P: Parser<'i, Output: Copy + Default>, S: Parser<'i>> P
113113
fn parse(&self, mut input: &'i [u8]) -> ParseResult<'i, Self::Output> {
114114
let mut output = ArrayVec::new();
115115

116+
let mut input_before_sep = input;
116117
let err = loop {
117118
let (v, remaining) = match self.parser.parse(input) {
118119
Ok(v) => v,
@@ -125,16 +126,16 @@ impl<'i, const N: usize, P: Parser<'i, Output: Copy + Default>, S: Parser<'i>> P
125126
if output.push(v).is_err() {
126127
return Err((ParseError::ExpectedLessItems(N), input));
127128
}
128-
input = remaining;
129+
input_before_sep = remaining;
129130

130-
match self.separator.parse(input) {
131+
match self.separator.parse(remaining) {
131132
Ok((_, remaining)) => input = remaining,
132133
Err(err) => break err,
133134
}
134135
};
135136

136137
if output.len() >= self.min_elements {
137-
Ok((output, input))
138+
Ok((output, input_before_sep))
138139
} else {
139140
Err(err)
140141
}
@@ -152,6 +153,7 @@ impl<'i, P: Parser<'i>, S: Parser<'i>> RepeatVec<P, S> {
152153
fn helper(&self, mut input: &'i [u8], consume_all: bool) -> ParseResult<'i, Vec<P::Output>> {
153154
let mut output = Vec::new();
154155

156+
let mut input_before_sep = input;
155157
let err = loop {
156158
let (v, remaining) = match self.parser.parse(input) {
157159
Ok(v) => v,
@@ -168,20 +170,20 @@ impl<'i, P: Parser<'i>, S: Parser<'i>> RepeatVec<P, S> {
168170
}
169171

170172
output.push(v);
171-
input = remaining;
173+
input_before_sep = remaining;
172174

173-
match self.separator.parse(input) {
175+
match self.separator.parse(remaining) {
174176
Ok((_, remaining)) => input = remaining,
175177
Err(err) => break err,
176178
}
177179
};
178180

179-
if (consume_all && !input.is_empty()) || output.len() < self.min_elements {
181+
if (consume_all && !input_before_sep.is_empty()) || output.len() < self.min_elements {
180182
// Return the last parsing error if this parser should consume the entire input and it
181183
// hasn't, or if the minimum number of elements isn't met.
182184
Err(err)
183185
} else {
184-
Ok((output, input))
186+
Ok((output, input_before_sep))
185187
}
186188
}
187189
}

crates/year2024/src/day05.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl Day05 {
2323
let updates_parser = num.repeat(b',', 1).repeat(parser::eol(), 1);
2424

2525
let (rule_list, updates) = rules_parser
26+
.with_eol()
2627
.with_eol()
2728
.then(updates_parser)
2829
.parse_complete(input)?;

0 commit comments

Comments
 (0)