1use super::MAX_NESTING_DEPTH;
4use crate::{Error, ErrorKind, Length, Result};
5
6#[derive(Clone, Debug)]
8pub(super) struct Position {
9 input_len: Length,
11
12 position: Length,
14
15 depth: usize,
17}
18
19impl Position {
20 pub(super) fn new(input_len: Length) -> Self {
22 Self {
23 input_len,
24 position: Length::ZERO,
25 depth: 0,
26 }
27 }
28
29 pub(super) fn advance(&mut self, amount: Length) -> Result<Length> {
33 let new_position = (self.position + amount)?;
34
35 if new_position > self.input_len {
36 return Err(ErrorKind::Incomplete {
37 expected_len: new_position,
38 actual_len: self.input_len,
39 }
40 .at(self.position));
41 }
42
43 self.position = new_position;
44 Ok(new_position)
45 }
46
47 pub(super) fn current(&self) -> Length {
49 self.position
50 }
51
52 pub(super) fn error(&mut self, kind: ErrorKind) -> Error {
54 kind.at(self.position)
55 }
56
57 pub(super) fn input_len(&self) -> Length {
59 self.input_len
60 }
61
62 pub(super) fn remaining_len(&self) -> Length {
64 debug_assert!(self.position <= self.input_len());
65 self.input_len.saturating_sub(self.position)
66 }
67
68 pub(super) fn split_nested(&mut self, len: Length) -> Result<Resumption> {
74 match self.depth.checked_add(1) {
75 Some(depth) if depth <= MAX_NESTING_DEPTH => self.depth = depth,
76 _ => return Err(self.error(ErrorKind::NestingDepth)),
77 }
78
79 let nested_input_len = (self.position + len)?;
80
81 if nested_input_len > self.input_len {
82 return Err(Error::incomplete(self.input_len));
83 }
84
85 let resumption = Resumption {
86 input_len: self.input_len,
87 };
88 self.input_len = nested_input_len;
89 Ok(resumption)
90 }
91
92 pub(super) fn resume_nested(&mut self, resumption: Resumption) {
94 self.input_len = resumption.input_len;
95 self.depth = self.depth.saturating_sub(1);
96 }
97}
98
99#[derive(Debug)]
101pub(super) struct Resumption {
102 input_len: Length,
104}
105
106#[cfg(test)]
107#[allow(clippy::unwrap_used)]
108mod tests {
109 use super::Position;
110 use crate::{ErrorKind, Length};
111
112 const EXAMPLE_LEN: Length = match Length::new_usize(42) {
113 Ok(len) => len,
114 Err(_) => panic!("invalid example len"),
115 };
116
117 #[test]
118 fn initial_state() {
119 let pos = Position::new(EXAMPLE_LEN);
120 assert_eq!(pos.input_len(), EXAMPLE_LEN);
121 assert_eq!(pos.current(), Length::ZERO);
122 }
123
124 #[test]
125 fn advance() {
126 let mut pos = Position::new(EXAMPLE_LEN);
127
128 let new_pos = pos.advance(Length::ONE).unwrap();
130 assert_eq!(new_pos, Length::ONE);
131 assert_eq!(pos.current(), Length::ONE);
132
133 let end_pos = pos.advance((EXAMPLE_LEN - Length::ONE).unwrap()).unwrap();
135 assert_eq!(end_pos, EXAMPLE_LEN);
136 assert_eq!(pos.current(), EXAMPLE_LEN);
137
138 let err = pos.advance(Length::ONE).unwrap_err();
140 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
141 }
142
143 #[test]
144 fn nested() {
145 let mut pos = Position::new(EXAMPLE_LEN);
146
147 let resumption = pos.split_nested(Length::ONE).unwrap();
149 assert_eq!(pos.current(), Length::ZERO);
150 assert_eq!(pos.input_len(), Length::ONE);
151
152 assert_eq!(pos.advance(Length::ONE).unwrap(), Length::ONE);
154
155 let err = pos.advance(Length::ONE).unwrap_err();
157 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
158
159 pos.resume_nested(resumption);
162
163 assert_eq!(pos.current(), Length::ONE);
164 assert_eq!(pos.input_len(), EXAMPLE_LEN);
165
166 let err = pos.split_nested(EXAMPLE_LEN).unwrap_err();
168 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
169 }
170}