1use crate::{Error, ErrorKind, Length, Result};
4
5#[derive(Clone, Debug)]
7pub(super) struct Position {
8 input_len: Length,
10
11 position: Length,
13
14 depth: usize,
16}
17
18impl Position {
19 const MAX_DEPTH: usize = 64;
21
22 pub(super) fn new(input_len: Length) -> Self {
24 Self {
25 input_len,
26 position: Length::ZERO,
27 depth: 0,
28 }
29 }
30
31 pub(super) fn advance(&mut self, amount: Length) -> Result<Length> {
35 let new_position = (self.position + amount)?;
36
37 if new_position > self.input_len {
38 return Err(ErrorKind::Incomplete {
39 expected_len: new_position,
40 actual_len: self.input_len,
41 }
42 .at(self.position));
43 }
44
45 self.position = new_position;
46 Ok(new_position)
47 }
48
49 pub(super) fn current(&self) -> Length {
51 self.position
52 }
53
54 pub(super) fn error(&mut self, kind: ErrorKind) -> Error {
56 kind.at(self.position)
57 }
58
59 pub(super) fn input_len(&self) -> Length {
61 self.input_len
62 }
63
64 pub(super) fn remaining_len(&self) -> Length {
66 debug_assert!(self.position <= self.input_len());
67 self.input_len.saturating_sub(self.position)
68 }
69
70 pub(super) fn split_nested(&mut self, len: Length) -> Result<Resumption> {
76 match self.depth.checked_add(1) {
77 Some(depth) if depth < Self::MAX_DEPTH => self.depth = depth,
78 _ => return Err(self.error(ErrorKind::NestingDepth)),
79 }
80
81 let nested_input_len = (self.position + len)?;
82
83 if nested_input_len > self.input_len {
84 return Err(Error::incomplete(self.input_len));
85 }
86
87 let resumption = Resumption {
88 input_len: self.input_len,
89 };
90 self.input_len = nested_input_len;
91 Ok(resumption)
92 }
93
94 pub(super) fn resume_nested(&mut self, resumption: Resumption) {
96 self.input_len = resumption.input_len;
97 self.depth = self.depth.saturating_sub(1);
98 }
99}
100
101#[derive(Debug)]
103pub(super) struct Resumption {
104 input_len: Length,
106}
107
108#[cfg(test)]
109#[allow(clippy::unwrap_used)]
110mod tests {
111 use super::Position;
112 use crate::{ErrorKind, Length};
113
114 const EXAMPLE_LEN: Length = match Length::new_usize(42) {
115 Ok(len) => len,
116 Err(_) => panic!("invalid example len"),
117 };
118
119 #[test]
120 fn initial_state() {
121 let pos = Position::new(EXAMPLE_LEN);
122 assert_eq!(pos.input_len(), EXAMPLE_LEN);
123 assert_eq!(pos.current(), Length::ZERO);
124 }
125
126 #[test]
127 fn advance() {
128 let mut pos = Position::new(EXAMPLE_LEN);
129
130 let new_pos = pos.advance(Length::ONE).unwrap();
132 assert_eq!(new_pos, Length::ONE);
133 assert_eq!(pos.current(), Length::ONE);
134
135 let end_pos = pos.advance((EXAMPLE_LEN - Length::ONE).unwrap()).unwrap();
137 assert_eq!(end_pos, EXAMPLE_LEN);
138 assert_eq!(pos.current(), EXAMPLE_LEN);
139
140 let err = pos.advance(Length::ONE).unwrap_err();
142 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
143 }
144
145 #[test]
146 fn nested() {
147 let mut pos = Position::new(EXAMPLE_LEN);
148
149 let resumption = pos.split_nested(Length::ONE).unwrap();
151 assert_eq!(pos.current(), Length::ZERO);
152 assert_eq!(pos.input_len(), Length::ONE);
153
154 assert_eq!(pos.advance(Length::ONE).unwrap(), Length::ONE);
156
157 let err = pos.advance(Length::ONE).unwrap_err();
159 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
160
161 pos.resume_nested(resumption);
164
165 assert_eq!(pos.current(), Length::ONE);
166 assert_eq!(pos.input_len(), EXAMPLE_LEN);
167
168 let err = pos.split_nested(EXAMPLE_LEN).unwrap_err();
170 assert!(matches!(err.kind(), ErrorKind::Incomplete { .. }));
171 }
172}