diff --git a/pest/src/parser_state.rs b/pest/src/parser_state.rs index c7ad44e9..1b7718df 100644 --- a/pest/src/parser_state.rs +++ b/pest/src/parser_state.rs @@ -1060,20 +1060,39 @@ impl<'i, R: RuleType> ParserState<'i, R> { } fn constrain_idxs(start_: i32, end_: Option, len: usize) -> Option> { - if start_ > len as i32 || end_.map_or(false, |e| e > len as i32) { return None } - let start = match negative_index(start_, len) { Some(s) => s, None => return None }; - let end = match end_ { - Some(end_) => match negative_index(end_, len) { Some(s) => s, None => return None }, - None => len, - }; + let start = normalize_index(start_, len)?; + let end = end_.map_or(Some(len), |e| normalize_index(e, len))?; Some(start..end) } -fn negative_index(i: i32, len: usize) -> Option { - if i >= 0 { +/// Normalizes the index using its sequence’s length. +/// Returns `None` if the normalized index is OOB. +fn normalize_index(i: i32, len: usize) -> Option { + if i > len as i32 { + None + } else if i >= 0 { Some(i as usize) } else { let real_i = len as i32 + i; if real_i >= 0 { Some(real_i as usize) } else { None } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn normalize_index_pos() { + assert_eq!(normalize_index(4, 6), Some(4)); + assert_eq!(normalize_index(5, 5), Some(5)); + assert_eq!(normalize_index(6, 3), None); + } + + #[test] + fn normalize_index_neg() { + assert_eq!(normalize_index(-4, 6), Some(2)); + assert_eq!(normalize_index(-5, 5), Some(0)); + assert_eq!(normalize_index(-6, 3), None); + } +} diff --git a/pest/src/stack.rs b/pest/src/stack.rs index b0c29c68..2d0f00eb 100644 --- a/pest/src/stack.rs +++ b/pest/src/stack.rs @@ -54,7 +54,7 @@ impl Stack { popped } - /// Returns an iterator to the current state of the cache in fifo order. + /// Returns an iterator to the current state of the cache in lifo order (top to bottom). #[allow(dead_code)] pub fn iter(&self) -> impl Iterator { self.cache.iter().rev()