Coverage Report

Created: 2025-07-23 06:21

/rust/registry/src/index.crates.io-6f17d22bba15001f/untrusted-0.9.0/src/reader.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015-2021 Brian Smith.
2
//
3
// Permission to use, copy, modify, and/or distribute this software for any
4
// purpose with or without fee is hereby granted, provided that the above
5
// copyright notice and this permission notice appear in all copies.
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15
use crate::{no_panic, Input};
16
17
/// A read-only, forward-only cursor into the data in an `Input`.
18
///
19
/// Using `Reader` to parse input helps to ensure that no byte of the input
20
/// will be accidentally processed more than once. Using `Reader` in
21
/// conjunction with `read_all` and `read_all_optional` helps ensure that no
22
/// byte of the input is accidentally left unprocessed. The methods of `Reader`
23
/// never panic, so `Reader` also assists the writing of panic-free code.
24
///
25
/// Intentionally avoids implementing `PartialEq` and `Eq` to avoid implicit
26
/// non-constant-time comparisons.
27
pub struct Reader<'a> {
28
    input: no_panic::Slice<'a>,
29
    i: usize,
30
}
31
32
/// Avoids writing the value or position to avoid creating a side channel,
33
/// though `Reader` can't avoid leaking the position via timing.
34
impl core::fmt::Debug for Reader<'_> {
35
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
36
0
        f.debug_struct("Reader").finish()
37
0
    }
38
}
39
40
impl<'a> Reader<'a> {
41
    /// Construct a new Reader for the given input. Use `read_all` or
42
    /// `read_all_optional` instead of `Reader::new` whenever possible.
43
    #[inline]
44
0
    pub fn new(input: Input<'a>) -> Self {
45
0
        Self {
46
0
            input: input.into_value(),
47
0
            i: 0,
48
0
        }
49
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::new
Unexecuted instantiation: <untrusted::reader::Reader>::new
Unexecuted instantiation: <untrusted::reader::Reader>::new
50
51
    /// Returns `true` if the reader is at the end of the input, and `false`
52
    /// otherwise.
53
    #[inline]
54
0
    pub fn at_end(&self) -> bool {
55
0
        self.i == self.input.len()
56
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::at_end
Unexecuted instantiation: <untrusted::reader::Reader>::at_end
Unexecuted instantiation: <untrusted::reader::Reader>::at_end
57
58
    /// Returns `true` if there is at least one more byte in the input and that
59
    /// byte is equal to `b`, and false otherwise.
60
    #[inline]
61
0
    pub fn peek(&self, b: u8) -> bool {
62
0
        match self.input.get(self.i) {
63
0
            Some(actual_b) => b == *actual_b,
64
0
            None => false,
65
        }
66
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::peek
Unexecuted instantiation: <untrusted::reader::Reader>::peek
Unexecuted instantiation: <untrusted::reader::Reader>::peek
67
68
    /// Reads the next input byte.
69
    ///
70
    /// Returns `Ok(b)` where `b` is the next input byte, or `Err(EndOfInput)`
71
    /// if the `Reader` is at the end of the input.
72
    #[inline]
73
0
    pub fn read_byte(&mut self) -> Result<u8, EndOfInput> {
74
0
        match self.input.get(self.i) {
75
0
            Some(b) => {
76
0
                self.i += 1; // safe from overflow; see Input::from().
77
0
                Ok(*b)
78
            }
79
0
            None => Err(EndOfInput),
80
        }
81
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::read_byte
Unexecuted instantiation: <untrusted::reader::Reader>::read_byte
Unexecuted instantiation: <untrusted::reader::Reader>::read_byte
82
83
    /// Skips `num_bytes` of the input, returning the skipped input as an
84
    /// `Input`.
85
    ///
86
    /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining,
87
    /// and `Err(EndOfInput)` otherwise.
88
    #[inline]
89
0
    pub fn read_bytes(&mut self, num_bytes: usize) -> Result<Input<'a>, EndOfInput> {
90
0
        let new_i = self.i.checked_add(num_bytes).ok_or(EndOfInput)?;
91
0
        let ret = self
92
0
            .input
93
0
            .subslice(self.i..new_i)
94
0
            .map(From::from)
95
0
            .ok_or(EndOfInput)?;
96
0
        self.i = new_i;
97
0
        Ok(ret)
98
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes
99
100
    /// Skips the reader to the end of the input, returning the skipped input
101
    /// as an `Input`.
102
    #[inline]
103
0
    pub fn read_bytes_to_end(&mut self) -> Input<'a> {
104
0
        let to_skip = self.input.len() - self.i;
105
0
        self.read_bytes(to_skip).unwrap()
106
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes_to_end
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes_to_end
Unexecuted instantiation: <untrusted::reader::Reader>::read_bytes_to_end
107
108
    /// Calls `read()` with the given input as a `Reader`. On success, returns a
109
    /// pair `(bytes_read, r)` where `bytes_read` is what `read()` consumed and
110
    /// `r` is `read()`'s return value.
111
0
    pub fn read_partial<F, R, E>(&mut self, read: F) -> Result<(Input<'a>, R), E>
112
0
    where
113
0
        F: FnOnce(&mut Reader<'a>) -> Result<R, E>,
114
0
    {
115
0
        let start = self.i;
116
0
        let r = read(self)?;
117
0
        let bytes_read = self.input.subslice(start..self.i).unwrap().into();
118
0
        Ok((bytes_read, r))
119
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::read_partial::<webpki::signed_data::parse_signed_data::{closure#0}, untrusted::input::Input, webpki::error::Error>
Unexecuted instantiation: <untrusted::reader::Reader>::read_partial::<_, _, _>
120
121
    /// Skips `num_bytes` of the input.
122
    ///
123
    /// Returns `Ok(i)` if there are at least `num_bytes` of input remaining,
124
    /// and `Err(EndOfInput)` otherwise.
125
    #[inline]
126
0
    pub fn skip(&mut self, num_bytes: usize) -> Result<(), EndOfInput> {
127
0
        self.read_bytes(num_bytes).map(|_| ())
Unexecuted instantiation: <untrusted::reader::Reader>::skip::{closure#0}
Unexecuted instantiation: <untrusted::reader::Reader>::skip::{closure#0}
128
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::skip
Unexecuted instantiation: <untrusted::reader::Reader>::skip
129
130
    /// Skips the reader to the end of the input.
131
    #[inline]
132
0
    pub fn skip_to_end(&mut self) {
133
0
        let _ = self.read_bytes_to_end();
134
0
    }
Unexecuted instantiation: <untrusted::reader::Reader>::skip_to_end
Unexecuted instantiation: <untrusted::reader::Reader>::skip_to_end
135
}
136
137
/// The error type used to indicate the end of the input was reached before the
138
/// operation could be completed.
139
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
140
pub struct EndOfInput;