1use crate::stream::AsBStr;
2use crate::stream::AsBytes;
3use crate::stream::Checkpoint;
4use crate::stream::Compare;
5use crate::stream::CompareResult;
6use crate::stream::FindSlice;
7use crate::stream::Location;
8use crate::stream::Needed;
9use crate::stream::Offset;
10#[cfg(feature = "unstable-recover")]
11#[cfg(feature = "std")]
12use crate::stream::Recover;
13use crate::stream::SliceLen;
14use crate::stream::Stream;
15use crate::stream::StreamIsPartial;
16use crate::stream::UpdateSlice;
17
18#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
86pub struct Partial<I> {
87 input: I,
88 partial: bool,
89}
90
91impl<I> Partial<I>
92where
93 I: StreamIsPartial,
94{
95 #[inline]
97 pub fn new(input: I) -> Self {
98 debug_assert!(
99 !I::is_partial_supported(),
100 "`Partial` can only wrap complete sources"
101 );
102 let partial = true;
103 Self { input, partial }
104 }
105
106 #[inline(always)]
108 pub fn into_inner(self) -> I {
109 self.input
110 }
111}
112
113impl<I> Default for Partial<I>
114where
115 I: Default + StreamIsPartial,
116{
117 #[inline]
118 fn default() -> Self {
119 Self::new(I::default())
120 }
121}
122
123impl<I> core::ops::Deref for Partial<I> {
124 type Target = I;
125
126 #[inline(always)]
127 fn deref(&self) -> &Self::Target {
128 &self.input
129 }
130}
131
132impl<I: core::fmt::Display> core::fmt::Display for Partial<I> {
133 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
134 self.input.fmt(f)
135 }
136}
137
138impl<I> SliceLen for Partial<I>
139where
140 I: SliceLen,
141{
142 #[inline(always)]
143 fn slice_len(&self) -> usize {
144 self.input.slice_len()
145 }
146}
147
148impl<I: Stream> Stream for Partial<I> {
149 type Token = <I as Stream>::Token;
150 type Slice = <I as Stream>::Slice;
151
152 type IterOffsets = <I as Stream>::IterOffsets;
153
154 type Checkpoint = Checkpoint<I::Checkpoint, Self>;
155
156 #[inline(always)]
157 fn iter_offsets(&self) -> Self::IterOffsets {
158 self.input.iter_offsets()
159 }
160 #[inline(always)]
161 fn eof_offset(&self) -> usize {
162 self.input.eof_offset()
163 }
164
165 #[inline(always)]
166 fn next_token(&mut self) -> Option<Self::Token> {
167 self.input.next_token()
168 }
169
170 #[inline(always)]
171 fn peek_token(&self) -> Option<Self::Token> {
172 self.input.peek_token()
173 }
174
175 #[inline(always)]
176 fn offset_for<P>(&self, predicate: P) -> Option<usize>
177 where
178 P: Fn(Self::Token) -> bool,
179 {
180 self.input.offset_for(predicate)
181 }
182 #[inline(always)]
183 fn offset_at(&self, tokens: usize) -> Result<usize, Needed> {
184 self.input.offset_at(tokens)
185 }
186 #[inline(always)]
187 fn next_slice(&mut self, offset: usize) -> Self::Slice {
188 self.input.next_slice(offset)
189 }
190 #[inline(always)]
191 unsafe fn next_slice_unchecked(&mut self, offset: usize) -> Self::Slice {
192 unsafe { self.input.next_slice_unchecked(offset) }
194 }
195 #[inline(always)]
196 fn peek_slice(&self, offset: usize) -> Self::Slice {
197 self.input.peek_slice(offset)
198 }
199 #[inline(always)]
200 unsafe fn peek_slice_unchecked(&self, offset: usize) -> Self::Slice {
201 unsafe { self.input.peek_slice_unchecked(offset) }
203 }
204
205 #[inline(always)]
206 fn checkpoint(&self) -> Self::Checkpoint {
207 Checkpoint::<_, Self>::new(self.input.checkpoint())
208 }
209 #[inline(always)]
210 fn reset(&mut self, checkpoint: &Self::Checkpoint) {
211 self.input.reset(&checkpoint.inner);
212 }
213
214 fn trace(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
215 self.input.trace(f)
216 }
217}
218
219impl<I> Location for Partial<I>
220where
221 I: Location,
222{
223 #[inline(always)]
224 fn previous_token_end(&self) -> usize {
225 self.input.previous_token_end()
226 }
227 #[inline(always)]
228 fn current_token_start(&self) -> usize {
229 self.input.current_token_start()
230 }
231}
232
233#[cfg(feature = "unstable-recover")]
234#[cfg(feature = "std")]
235impl<I, E> Recover<E> for Partial<I>
236where
237 I: Recover<E>,
238 I: Stream,
239{
240 #[inline(always)]
241 fn record_err(
242 &mut self,
243 _token_start: &Self::Checkpoint,
244 _err_start: &Self::Checkpoint,
245 err: E,
246 ) -> Result<(), E> {
247 Err(err)
248 }
249
250 #[inline(always)]
252 fn is_recovery_supported() -> bool {
253 false
254 }
255}
256
257impl<I> StreamIsPartial for Partial<I>
258where
259 I: StreamIsPartial,
260{
261 type PartialState = bool;
262
263 #[inline]
264 fn complete(&mut self) -> Self::PartialState {
265 core::mem::replace(&mut self.partial, false)
266 }
267
268 #[inline]
269 fn restore_partial(&mut self, state: Self::PartialState) {
270 self.partial = state;
271 }
272
273 #[inline(always)]
274 fn is_partial_supported() -> bool {
275 true
276 }
277
278 #[inline(always)]
279 fn is_partial(&self) -> bool {
280 self.partial
281 }
282}
283
284impl<I> Offset for Partial<I>
285where
286 I: Stream,
287{
288 #[inline(always)]
289 fn offset_from(&self, start: &Self) -> usize {
290 self.offset_from(&start.checkpoint())
291 }
292}
293
294impl<I> Offset<<Partial<I> as Stream>::Checkpoint> for Partial<I>
295where
296 I: Stream,
297{
298 #[inline(always)]
299 fn offset_from(&self, other: &<Partial<I> as Stream>::Checkpoint) -> usize {
300 self.checkpoint().offset_from(other)
301 }
302}
303
304impl<I> AsBytes for Partial<I>
305where
306 I: AsBytes,
307{
308 #[inline(always)]
309 fn as_bytes(&self) -> &[u8] {
310 self.input.as_bytes()
311 }
312}
313
314impl<I> AsBStr for Partial<I>
315where
316 I: AsBStr,
317{
318 #[inline(always)]
319 fn as_bstr(&self) -> &[u8] {
320 self.input.as_bstr()
321 }
322}
323
324impl<I, T> Compare<T> for Partial<I>
325where
326 I: Compare<T>,
327{
328 #[inline(always)]
329 fn compare(&self, t: T) -> CompareResult {
330 self.input.compare(t)
331 }
332}
333
334impl<I, T> FindSlice<T> for Partial<I>
335where
336 I: FindSlice<T>,
337{
338 #[inline(always)]
339 fn find_slice(&self, substr: T) -> Option<core::ops::Range<usize>> {
340 self.input.find_slice(substr)
341 }
342}
343
344impl<I> UpdateSlice for Partial<I>
345where
346 I: UpdateSlice,
347{
348 #[inline(always)]
349 fn update_slice(self, inner: Self::Slice) -> Self {
350 Partial {
351 input: I::update_slice(self.input, inner),
352 partial: self.partial,
353 }
354 }
355}