rjiter/
rjiter.rs

1use embedded_io::{Error as _, Read, Write};
2
3use crate::buffer::Buffer;
4use crate::buffer::ChangeFlag;
5use crate::error::{can_retry_if_partial, Error as RJiterError, ErrorType, Result as RJiterResult};
6use crate::jiter::{
7    Jiter, JiterResult, JsonErrorType, JsonValue, LinePosition, NumberAny, NumberInt, Peek,
8};
9
10/// Streaming JSON parser, a wrapper around `Jiter`.
11pub struct RJiter<'rj, R: Read> {
12    jiter: Jiter<'rj>,
13    buffer: Buffer<'rj, R>,
14}
15
16impl<R: Read> core::fmt::Debug for RJiter<'_, R> {
17    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18        write!(
19            f,
20            "RJiter {{ jiter: {:?}, buffer: {:?} }}",
21            self.jiter, self.buffer
22        )
23    }
24}
25
26impl<'rj, R: Read> RJiter<'rj, R> {
27    /// Constructs a new `RJiter`.
28    ///
29    /// # Arguments
30    /// - `reader`: The json stream
31    /// - `buf`: The working buffer
32    pub fn new(reader: &'rj mut R, buf: &'rj mut [u8]) -> Self {
33        #[allow(unsafe_code)]
34        let buf_alias = unsafe {
35            #[allow(mutable_transmutes)]
36            #[allow(clippy::transmute_ptr_to_ptr)]
37            core::mem::transmute::<&[u8], &'rj mut [u8]>(buf)
38        };
39        let buffer = Buffer::new(reader, buf_alias);
40        // `0 <= buffer.n_bytes <= buf.len()` by the `Buffer` contract
41        #[allow(clippy::indexing_slicing)]
42        let jiter = Jiter::new(&buf[..buffer.n_bytes]);
43
44        RJiter { jiter, buffer }
45    }
46
47    fn create_new_jiter(&mut self) {
48        // `0 <= buffer.n_bytes <= buf.len()` by the `Buffer` contract
49        #[allow(clippy::indexing_slicing)]
50        let jiter_buffer_2 = &self.buffer.buf[..self.buffer.n_bytes];
51        #[allow(unsafe_code)]
52        let jiter_buffer = unsafe { core::mem::transmute::<&[u8], &'rj [u8]>(jiter_buffer_2) };
53        self.jiter = Jiter::new(jiter_buffer);
54    }
55
56    //  ------------------------------------------------------------
57    // Jiter wrappers
58    //
59
60    /// See `Jiter::peek`
61    /// # Errors
62    /// `IoError` or `JiterError`
63    pub fn peek(&mut self) -> RJiterResult<Peek> {
64        self.loop_until_success(jiter::Jiter::peek, None, false)
65    }
66
67    /// See `Jiter::known_array`
68    /// # Errors
69    /// `IoError` or `JiterError`
70    pub fn known_array(&mut self) -> RJiterResult<Option<Peek>> {
71        self.loop_until_success(jiter::Jiter::known_array, Some(b'['), false)
72    }
73
74    /// See `Jiter::known_bool`
75    /// # Errors
76    /// `IoError` or `JiterError`
77    pub fn known_bool(&mut self, peek: Peek) -> RJiterResult<bool> {
78        self.loop_until_success(|j| j.known_bool(peek), None, false)
79    }
80
81    /// See `Jiter::known_bytes`
82    /// # Errors
83    /// `IoError` or `JiterError`
84    pub fn known_bytes(&mut self) -> RJiterResult<&[u8]> {
85        #[allow(unsafe_code)]
86        let f = |j: &mut Jiter<'rj>| unsafe {
87            core::mem::transmute::<JiterResult<&[u8]>, JiterResult<&'rj [u8]>>(j.known_bytes())
88        };
89        self.loop_until_success(f, None, false)
90    }
91
92    /// See `Jiter::known_float`
93    /// # Errors
94    /// `IoError` or `JiterError`
95    pub fn known_float(&mut self, peek: Peek) -> RJiterResult<f64> {
96        self.loop_until_success(|j| j.known_float(peek), None, true)
97    }
98
99    /// See `Jiter::known_int`
100    /// # Errors
101    /// `IoError` or `JiterError`
102    pub fn known_int(&mut self, peek: Peek) -> RJiterResult<NumberInt> {
103        self.loop_until_success(|j| j.known_int(peek), None, true)
104    }
105
106    /// See `Jiter::known_null`
107    /// # Errors
108    /// `IoError` or `JiterError`
109    pub fn known_null(&mut self) -> RJiterResult<()> {
110        self.loop_until_success(jiter::Jiter::known_null, None, false)
111    }
112
113    /// See `Jiter::known_number`
114    /// # Errors
115    /// `IoError` or `JiterError`
116    pub fn known_number(&mut self, peek: Peek) -> RJiterResult<NumberAny> {
117        self.loop_until_success(|j| j.known_number(peek), None, true)
118    }
119
120    /// See `Jiter::known_object`
121    /// # Errors
122    /// `IoError` or `JiterError`
123    pub fn known_object(&mut self) -> RJiterResult<Option<&str>> {
124        #[allow(unsafe_code)]
125        let f = |j: &mut Jiter<'rj>| unsafe {
126            core::mem::transmute::<JiterResult<Option<&str>>, JiterResult<Option<&'rj str>>>(
127                j.known_object(),
128            )
129        };
130        self.loop_until_success(f, Some(b'{'), false)
131    }
132
133    /// See `Jiter::known_skip`
134    /// # Errors
135    /// `IoError` or `JiterError`
136    pub fn known_skip(&mut self, peek: Peek) -> RJiterResult<()> {
137        self.loop_until_success(|j| j.known_skip(peek), None, true)
138    }
139
140    /// See `Jiter::known_str`
141    /// # Errors
142    /// `IoError` or `JiterError`
143    pub fn known_str(&mut self) -> RJiterResult<&str> {
144        #[allow(unsafe_code)]
145        let f = |j: &mut Jiter<'rj>| unsafe {
146            core::mem::transmute::<JiterResult<&str>, JiterResult<&'rj str>>(j.known_str())
147        };
148        self.loop_until_success(f, None, false)
149    }
150
151    /// See `Jiter::known_value`
152    /// # Errors
153    /// `IoError` or `JiterError`
154    pub fn known_value(&mut self, peek: Peek) -> RJiterResult<JsonValue<'rj>> {
155        self.loop_until_success(|j| j.known_value(peek), None, true)
156    }
157
158    /// See `Jiter::known_value_owned`
159    /// # Errors
160    /// `IoError` or `JiterError`
161    pub fn known_value_owned(&mut self, peek: Peek) -> RJiterResult<JsonValue<'static>> {
162        self.loop_until_success(|j| j.known_value_owned(peek), None, true)
163    }
164
165    /// See `Jiter::next_array`
166    /// # Errors
167    /// `IoError` or `JiterError`
168    pub fn next_array(&mut self) -> RJiterResult<Option<Peek>> {
169        self.loop_until_success(jiter::Jiter::next_array, Some(b'['), false)
170    }
171
172    /// See `Jiter::array_step`
173    /// # Errors
174    /// `IoError` or `JiterError`
175    pub fn array_step(&mut self) -> RJiterResult<Option<Peek>> {
176        self.loop_until_success(jiter::Jiter::array_step, Some(b','), false)
177    }
178
179    /// See `Jiter::next_bool`
180    /// # Errors
181    /// `IoError` or `JiterError`
182    pub fn next_bool(&mut self) -> RJiterResult<bool> {
183        self.loop_until_success(jiter::Jiter::next_bool, None, false)
184    }
185
186    /// See `Jiter::next_bytes`
187    /// # Errors
188    /// `IoError` or `JiterError`
189    pub fn next_bytes(&mut self) -> RJiterResult<&[u8]> {
190        #[allow(unsafe_code)]
191        let f = |j: &mut Jiter<'rj>| unsafe {
192            core::mem::transmute::<JiterResult<&[u8]>, JiterResult<&'rj [u8]>>(j.next_bytes())
193        };
194        self.loop_until_success(f, None, false)
195    }
196
197    /// See `Jiter::next_float`
198    /// # Errors
199    /// `IoError` or `JiterError`
200    pub fn next_float(&mut self) -> RJiterResult<f64> {
201        self.loop_until_success(jiter::Jiter::next_float, None, true)
202    }
203
204    /// See `Jiter::next_int`
205    /// # Errors
206    /// `IoError` or `JiterError`
207    pub fn next_int(&mut self) -> RJiterResult<NumberInt> {
208        self.loop_until_success(jiter::Jiter::next_int, None, true)
209    }
210
211    /// See `Jiter::next_key`
212    /// # Errors
213    /// `IoError` or `JiterError`
214    pub fn next_key(&mut self) -> RJiterResult<Option<&str>> {
215        #[allow(unsafe_code)]
216        let f = |j: &mut Jiter<'rj>| unsafe {
217            core::mem::transmute::<JiterResult<Option<&str>>, JiterResult<Option<&'rj str>>>(
218                j.next_key(),
219            )
220        };
221        self.loop_until_success(f, Some(b','), false)
222    }
223
224    /// See `Jiter::next_key_bytes`
225    /// # Errors
226    /// `IoError` or `JiterError`
227    pub fn next_key_bytes(&mut self) -> RJiterResult<Option<&[u8]>> {
228        #[allow(unsafe_code)]
229        let f = |j: &mut Jiter<'rj>| unsafe {
230            core::mem::transmute::<JiterResult<Option<&[u8]>>, JiterResult<Option<&'rj [u8]>>>(
231                j.next_key_bytes(),
232            )
233        };
234        self.loop_until_success(f, Some(b','), false)
235    }
236
237    /// See `Jiter::next_null`
238    /// # Errors
239    /// `IoError` or `JiterError`
240    pub fn next_null(&mut self) -> RJiterResult<()> {
241        self.loop_until_success(jiter::Jiter::next_null, None, false)
242    }
243
244    /// See `Jiter::next_number`
245    /// # Errors
246    /// `IoError` or `JiterError`
247    pub fn next_number(&mut self) -> RJiterResult<NumberAny> {
248        self.loop_until_success(jiter::Jiter::next_number, None, true)
249    }
250
251    /// See `Jiter::next_number_bytes`
252    /// # Errors
253    /// `IoError` or `JiterError`
254    pub fn next_number_bytes(&mut self) -> RJiterResult<&[u8]> {
255        #[allow(unsafe_code)]
256        let f = |j: &mut Jiter<'rj>| unsafe {
257            core::mem::transmute::<JiterResult<&[u8]>, JiterResult<&'rj [u8]>>(
258                j.next_number_bytes(),
259            )
260        };
261        self.loop_until_success(f, None, true)
262    }
263
264    /// See `Jiter::next_object`
265    /// # Errors
266    /// `IoError` or `JiterError`
267    pub fn next_object(&mut self) -> RJiterResult<Option<&str>> {
268        #[allow(unsafe_code)]
269        let f = |j: &mut Jiter<'rj>| unsafe {
270            core::mem::transmute::<JiterResult<Option<&str>>, JiterResult<Option<&'rj str>>>(
271                j.next_object(),
272            )
273        };
274        self.loop_until_success(f, Some(b'{'), false)
275    }
276
277    /// See `Jiter::next_object_bytes`
278    /// # Errors
279    /// `IoError` or `JiterError`
280    pub fn next_object_bytes(&mut self) -> RJiterResult<Option<&[u8]>> {
281        #[allow(unsafe_code)]
282        let f = |j: &mut Jiter<'rj>| unsafe {
283            core::mem::transmute::<JiterResult<Option<&[u8]>>, JiterResult<Option<&'rj [u8]>>>(
284                j.next_object_bytes(),
285            )
286        };
287        self.loop_until_success(f, Some(b'{'), false)
288    }
289
290    /// See `Jiter::next_skip`
291    /// # Errors
292    /// `IoError` or `JiterError`
293    pub fn next_skip(&mut self) -> RJiterResult<()> {
294        self.loop_until_success(jiter::Jiter::next_skip, None, true)
295    }
296
297    /// See `Jiter::next_str`
298    /// # Errors
299    /// `IoError` or `JiterError`
300    pub fn next_str(&mut self) -> RJiterResult<&str> {
301        #[allow(unsafe_code)]
302        let f = |j: &mut Jiter<'rj>| unsafe {
303            core::mem::transmute::<JiterResult<&str>, JiterResult<&'rj str>>(j.next_str())
304        };
305        self.loop_until_success(f, None, false)
306    }
307
308    /// See `Jiter::next_value`
309    /// # Errors
310    /// `IoError` or `JiterError`
311    pub fn next_value(&mut self) -> RJiterResult<JsonValue<'rj>> {
312        self.loop_until_success(jiter::Jiter::next_value, None, true)
313    }
314
315    /// See `Jiter::next_value_owned`
316    /// # Errors
317    /// `IoError` or `JiterError`
318    pub fn next_value_owned(&mut self) -> RJiterResult<JsonValue<'static>> {
319        self.loop_until_success(jiter::Jiter::next_value_owned, None, true)
320    }
321
322    //  ------------------------------------------------------------
323    // The implementation of Jiter wrappers
324    //
325
326    fn loop_until_success<T, F>(
327        &mut self,
328        mut f: F,
329        skip_spaces_token: Option<u8>,
330        should_eager_consume: bool,
331    ) -> RJiterResult<T>
332    where
333        F: FnMut(&mut Jiter<'rj>) -> JiterResult<T>,
334        T: core::fmt::Debug,
335    {
336        // Error-result makes `false`,
337        // Ok-result makes `true`, except if the grandcaller hints (`should_eager_consume`) that
338        // end of the buffer can be a false positive (e.g. when parsing a number).
339        fn downgrade_ok_if_eof<T>(
340            result: &JiterResult<T>,
341            should_eager_consume: bool,
342            jiter: &Jiter,
343            n_bytes: usize,
344        ) -> bool {
345            if !result.is_ok() {
346                return false;
347            }
348            if !should_eager_consume {
349                return true;
350            }
351            if jiter.current_index() < n_bytes {
352                return true;
353            }
354            false
355        }
356        let jiter_pos = self.jiter.current_index();
357
358        let result = f(&mut self.jiter);
359        let is_ok = downgrade_ok_if_eof(
360            &result,
361            should_eager_consume,
362            &self.jiter,
363            self.buffer.n_bytes,
364        );
365        if is_ok {
366            // `result` is always `Ok`
367            if let Ok(value) = result {
368                return Ok(value);
369            }
370        }
371
372        self.skip_spaces_feeding(jiter_pos, skip_spaces_token)?;
373
374        loop {
375            let result = f(&mut self.jiter);
376
377            if let Err(e) = &result {
378                if !can_retry_if_partial(e) {
379                    return Err(RJiterError::from_jiter_error(
380                        self.current_index(),
381                        e.clone(),
382                    ));
383                }
384            }
385
386            if result.is_ok() {
387                let really_ok = downgrade_ok_if_eof(
388                    &result,
389                    should_eager_consume,
390                    &self.jiter,
391                    self.buffer.n_bytes,
392                );
393                if really_ok {
394                    // `result` is always `Ok`
395                    if let Ok(value) = result {
396                        return Ok(value);
397                    }
398                }
399            }
400
401            let n_read = self.buffer.read_more();
402            match n_read {
403                Err(e) => return Err(e),
404                Ok(0) => {
405                    // EOF is reached in the error state
406                    return result
407                        .map_err(|e| RJiterError::from_jiter_error(self.current_index(), e));
408                }
409                Ok(_) => {
410                    self.create_new_jiter();
411                }
412            }
413        }
414    }
415
416    // If the transparent is found after skipping spaces, skip also spaces after the transparent token
417    // If any space is skipped, feed the buffer content to the position 0
418    // This function should be called only in a retry handler, otherwise it worsens performance
419    fn skip_spaces_feeding(
420        &mut self,
421        jiter_pos: usize,
422        transparent_token: Option<u8>,
423    ) -> RJiterResult<()> {
424        let to_pos = 0;
425        let change_flag = ChangeFlag::new(&self.buffer);
426
427        if jiter_pos > to_pos {
428            self.buffer.shift_buffer(to_pos, jiter_pos);
429        }
430        self.buffer.skip_spaces(to_pos)?;
431        if let Some(transparent_token) = transparent_token {
432            if to_pos >= self.buffer.n_bytes {
433                self.buffer.read_more()?;
434            }
435            // `0 <= to_pos` (usize), `to_pos < buffer.n_bytes` (if check), `n_bytes <= buf.len()` by the `Buffer` contract
436            #[allow(clippy::indexing_slicing)]
437            if to_pos < self.buffer.n_bytes && self.buffer.buf[to_pos] == transparent_token {
438                self.buffer.skip_spaces(to_pos + 1)?;
439            }
440        }
441
442        if change_flag.is_changed(&self.buffer) {
443            self.create_new_jiter();
444        }
445        Ok(())
446    }
447
448    /// See `Jiter::finish`
449    /// # Errors
450    /// `IoError` or `JiterError`
451    pub fn finish(&mut self) -> RJiterResult<()> {
452        loop {
453            let finish_in_this_buf = self.jiter.finish();
454            // Error here is actually not an error, but a marker that something is found
455            // and therefore the jiter is not at the end of the json
456            if let Err(e) = finish_in_this_buf {
457                return Err(RJiterError::from_jiter_error(self.current_index(), e));
458            }
459            // The current buffer was all only spaces. Read more.
460            if self.jiter.current_index() < self.buffer.buf.len() {
461                let n_new_bytes = self.buffer.read_more()?;
462                // The end of the json is reached
463                if n_new_bytes == 0 {
464                    return Ok(());
465                }
466            }
467            self.buffer.shift_buffer(0, self.jiter.current_index());
468            self.create_new_jiter();
469        }
470    }
471
472    //  ------------------------------------------------------------
473
474    /// Get the current index of the parser.
475    #[must_use]
476    pub fn current_index(&self) -> usize {
477        self.jiter.current_index() + self.buffer.n_shifted_out
478    }
479
480    /// Get the current `LinePosition` of the parser.
481    #[must_use]
482    pub fn error_position(&self, index: usize) -> LinePosition {
483        let index = index - self.buffer.n_shifted_out;
484        let pos = self.jiter.error_position(index);
485        LinePosition::new(
486            pos.line + self.buffer.pos_shifted.line,
487            pos.column + self.buffer.pos_shifted.column,
488        )
489    }
490
491    //  ------------------------------------------------------------
492    // Pass-through long strings and bytes
493
494    //
495    // Contract for `write_segment`:
496    // - arg 1: `self.buffer.buf`,
497    // - arg 2: `1 < segment_end_pos <= self.buffer.n_bytes - 1 <= self.buffer.buf.len() - 1`,
498    //          or `1 < segment_end_pos <= self.buffer.n_bytes <= 7`,
499    //
500    fn handle_long<F, T, W: Write>(
501        &mut self,
502        parser: F,
503        writer: &mut W,
504        write_completed: impl Fn(T, usize, &mut W) -> RJiterResult<()>,
505        write_segment: impl Fn(&mut [u8], usize, usize, &mut W) -> RJiterResult<()>,
506    ) -> RJiterResult<()>
507    where
508        F: Fn(&mut Jiter<'rj>) -> JiterResult<T>,
509        T: core::fmt::Debug,
510    {
511        loop {
512            // Handle simple cases:
513            // - The string is completed
514            // - The error is not recoverable
515            let result = parser(&mut self.jiter);
516            if let Ok(value) = result {
517                write_completed(value, self.current_index(), writer)?;
518                return Ok(());
519            }
520            // We need `err` in the scope later, therefore we don't use `match` for `result`
521            // The Ok-arm is handled above
522            #[allow(clippy::unwrap_used)]
523            let err = result.unwrap_err();
524            if !can_retry_if_partial(&err) {
525                return Err(RJiterError::from_jiter_error(self.current_index(), err));
526            }
527
528            // Move the string to the beginning of the buffer to avoid corner cases.
529            // This code runs at most once, and only on the first loop iteration.
530            if self.jiter.current_index() > 0 {
531                self.buffer.shift_buffer(0, self.jiter.current_index());
532                self.create_new_jiter();
533            }
534
535            // Current state: the string is not completed
536            // Find out a segment to write
537
538            #[allow(clippy::indexing_slicing)]
539            let bs_pos = self.buffer.buf[..self.buffer.n_bytes]
540                .iter()
541                .position(|&b| b == b'\\');
542            let segment_end_pos = match bs_pos {
543                // No backslash: the segment is the whole buffer
544                // `-1`: To write a segment, the writer needs an extra byte to put the quote character
545                None => {
546                    if self.buffer.n_bytes == 0 {
547                        0
548                    } else {
549                        self.buffer.n_bytes - 1
550                    }
551                }
552                // Backslash is somewhere in the buffer
553                // The segment is the part of the buffer before the backslash
554                Some(bs_pos) if bs_pos > 1 => bs_pos,
555                // Backslash is the first byte of the buffer
556                // The segment is the escape sequence
557                Some(bs_pos) => {
558                    let buf_len = self.buffer.n_bytes;
559                    // [QUOTE, SLASH, CHAR, ....]
560                    if buf_len < 3 {
561                        bs_pos
562                    } else {
563                        // `buf_len >= 3` in this branch
564                        #[allow(clippy::indexing_slicing)]
565                        let after_bs = self.buffer.buf[2];
566                        if after_bs != b'u' && after_bs != b'U' {
567                            bs_pos + 2
568                        } else {
569                            // [QUOTE, SLASH, u, HEXDEC, HEXDEC, HEXDEC, HEXDEC, ....]
570                            if buf_len < 7 {
571                                bs_pos
572                            } else {
573                                bs_pos + 6
574                            }
575                        }
576                    }
577                }
578            };
579
580            // Correct the segment end position to not break a unicode code point
581            let segment_end_pos = (0..=segment_end_pos)
582                .rev()
583                .find(
584                    #[allow(clippy::indexing_slicing)]
585                    |&pos| is_utf8_leading_byte(self.buffer.buf[pos]),
586                )
587                .unwrap_or(0);
588
589            // Write the segment
590            if segment_end_pos > 1 {
591                write_segment(
592                    self.buffer.buf,
593                    segment_end_pos,
594                    self.current_index(),
595                    writer,
596                )?;
597                self.buffer.shift_buffer(1, segment_end_pos);
598            }
599
600            // Read more and repeat
601            let n_new_bytes = self.buffer.read_more()?;
602            match n_new_bytes {
603                0 => return Err(RJiterError::from_jiter_error(self.current_index(), err)),
604                1.. => self.create_new_jiter(),
605            }
606        }
607    }
608
609    /// Write-read-write-read-... until the end of the json string.
610    /// The bytes are written as such, without transforming them.
611    /// This function is useful to copy a long json string to another json.
612    ///
613    /// Rjiter should be positioned at the beginning of the json string, on a quote character.
614    /// Bounding quotes are not included in the output.
615    ///
616    /// # Errors
617    /// `IoError` or `JiterError`
618    pub fn write_long_bytes<W: Write>(&mut self, writer: &mut W) -> RJiterResult<()> {
619        fn write_completed<W: Write>(
620            bytes: &[u8],
621            index: usize,
622            writer: &mut W,
623        ) -> RJiterResult<()> {
624            writer.write_all(bytes).map_err(|e| RJiterError {
625                error_type: ErrorType::IoError { kind: e.kind() },
626                index,
627            })
628        }
629        fn write_segment<W: Write>(
630            bytes: &mut [u8],
631            end_pos: usize,
632            index: usize,
633            writer: &mut W,
634        ) -> RJiterResult<()> {
635            // See the `write_long` contract. May panic for a small buffer (less than 7 bytes)
636            #[allow(clippy::indexing_slicing)]
637            writer
638                .write_all(&bytes[1..end_pos])
639                .map_err(|e| RJiterError {
640                    error_type: ErrorType::IoError { kind: e.kind() },
641                    index,
642                })
643        }
644        #[allow(unsafe_code)]
645        let parser = |j: &mut Jiter<'rj>| unsafe {
646            core::mem::transmute::<JiterResult<&[u8]>, JiterResult<&'rj [u8]>>(j.known_bytes())
647        };
648        self.handle_long(parser, writer, write_completed, write_segment)
649    }
650
651    /// Write-read-write-read-... until the end of the json string.
652    /// Converts the json escapes to the corresponding characters.
653    ///
654    /// Rjiter should be positioned at the beginning of the json string, on a quote character.
655    /// Bounding quotes are not included in the output.
656    ///
657    /// # Errors
658    /// `IoError` or `JiterError`
659    pub fn write_long_str<W: Write>(&mut self, writer: &mut W) -> RJiterResult<()> {
660        fn write_completed<W: Write>(
661            string: &str,
662            index: usize,
663            writer: &mut W,
664        ) -> RJiterResult<()> {
665            writer
666                .write_all(string.as_bytes())
667                .map_err(|e| RJiterError {
668                    error_type: ErrorType::IoError { kind: e.kind() },
669                    index,
670                })
671        }
672        fn write_segment<W: Write>(
673            bytes: &mut [u8],
674            end_pos: usize,
675            index: usize,
676            writer: &mut W,
677        ) -> RJiterResult<()> {
678            // From the `write_long` contract for a big buffer: `1 < end_pos <= self.buffer.n_bytes - 1`
679            // May panic for a small buffer (less than 7 bytes)
680            #[allow(clippy::indexing_slicing)]
681            let orig_char = bytes[end_pos];
682            #[allow(clippy::indexing_slicing)]
683            {
684                bytes[end_pos] = b'"';
685            }
686            #[allow(clippy::indexing_slicing)]
687            let sub_jiter_buf = &bytes[..=end_pos];
688            #[allow(unsafe_code)]
689            let sub_jiter_buf = unsafe { core::mem::transmute::<&[u8], &[u8]>(sub_jiter_buf) };
690            let mut sub_jiter = Jiter::new(sub_jiter_buf);
691            let sub_result = sub_jiter.known_str();
692            #[allow(clippy::indexing_slicing)]
693            {
694                bytes[end_pos] = orig_char;
695            }
696
697            match sub_result {
698                Ok(string) => writer
699                    .write_all(string.as_bytes())
700                    .map_err(|e| RJiterError {
701                        error_type: ErrorType::IoError { kind: e.kind() },
702                        index,
703                    }),
704                Err(e) => Err(RJiterError::from_jiter_error(index, e)),
705            }
706        }
707        #[allow(unsafe_code)]
708        let parser = |j: &mut Jiter<'rj>| unsafe {
709            core::mem::transmute::<JiterResult<&str>, JiterResult<&'rj str>>(j.known_str())
710        };
711        self.handle_long(parser, writer, write_completed, write_segment)
712    }
713
714    //  ------------------------------------------------------------
715    // Skip token
716    //
717
718    /// Skip the token if found, otherwise return an error.
719    /// `RJiter` should be positioned at the beginning of the potential token using `peek()` or `finish()`
720    ///
721    /// # Errors
722    /// `IoError` or `RJiterError(ExpectedSomeIdent)`
723    pub fn known_skip_token(&mut self, token: &[u8]) -> RJiterResult<()> {
724        let change_flag = ChangeFlag::new(&self.buffer);
725        let mut pos = self.jiter.current_index();
726        let mut err_flag = false;
727
728        // Read enough bytes to have the token
729        if pos + token.len() >= self.buffer.n_bytes {
730            self.buffer.shift_buffer(0, pos);
731            pos = 0;
732        }
733        while self.buffer.n_bytes < pos + token.len() {
734            let n_new_bytes = self.buffer.read_more()?;
735            if n_new_bytes == 0 {
736                // Not an error for the caller, just a normal end of the json
737                // The code should create a new Jiter. Doing so below
738                err_flag = true;
739                break;
740            }
741        }
742
743        // Find the token
744        let found = if err_flag {
745            false
746        } else {
747            // `pos` is `jiter.current_index()` or `0`
748            #[allow(clippy::indexing_slicing)]
749            let buf_view = &mut self.buffer.buf[pos..self.buffer.n_bytes];
750            buf_view.starts_with(token)
751        };
752
753        // Sync the Jiter
754        if found {
755            self.buffer.shift_buffer(0, pos + token.len());
756        }
757        if change_flag.is_changed(&self.buffer) {
758            self.create_new_jiter();
759        }
760
761        // Result
762        if found {
763            return Ok(());
764        }
765        Err(RJiterError::from_json_error(
766            self.current_index(),
767            JsonErrorType::ExpectedSomeIdent,
768        ))
769    }
770}
771
772fn is_utf8_leading_byte(b: u8) -> bool {
773    // Linters suggests to use `!(0b1000_0000..0b1100_0000).contains(&b)`,
774    // but for me the suggestion looks much less readable
775    #[allow(clippy::manual_range_contains)]
776    let flag = (b < 0b1000_0000) || (b >= 0b1100_0000);
777    flag
778}