1use super::Reader;
4use crate::{Decode, Error, ErrorKind, Header, Length, Result};
5use core::cell::RefCell;
6
7#[allow(clippy::integer_arithmetic)]
8mod utils {
9    use crate::{Error, Length, Result};
10    use pem_rfc7468::Decoder;
11
12    #[derive(Clone)]
13    pub(super) struct BufReader<'i> {
14        decoder: Decoder<'i>,
16
17        remaining: usize,
19
20        buf: [u8; BufReader::CAPACITY],
22
23        pos: usize,
25
26        cap: usize,
28    }
29
30    impl<'i> BufReader<'i> {
31        const CAPACITY: usize = 256;
32
33        pub fn new(pem: &'i [u8]) -> Result<Self> {
34            let decoder = Decoder::new(pem)?;
35            let remaining = decoder.remaining_len();
36
37            Ok(Self {
38                decoder,
39                remaining,
40                buf: [0u8; 256],
41                pos: 0,
42                cap: 0,
43            })
44        }
45
46        pub fn remaining_len(&self) -> usize {
47            self.decoder.remaining_len() + self.cap - self.pos
48        }
49
50        fn fill_buffer(&mut self) -> Result<()> {
51            debug_assert!(self.pos <= self.cap);
52
53            if self.is_empty() {
54                self.pos = 0;
55                self.cap = 0;
56            }
57
58            let end = (self.cap + self.remaining).min(Self::CAPACITY);
59            let writable_slice = &mut self.buf[self.cap..end];
60            if writable_slice.is_empty() {
61                return Ok(());
62            }
63
64            let wrote = self.decoder.decode(writable_slice)?.len();
65            if wrote == 0 {
66                return Err(Error::incomplete(Length::try_from(self.pos)?));
67            }
68
69            self.cap += wrote;
70            self.remaining -= wrote;
71            debug_assert!(self.cap <= Self::CAPACITY);
72
73            Ok(())
74        }
75
76        pub fn type_label(&self) -> &'i str {
79            self.decoder.type_label()
80        }
81
82        fn is_empty(&self) -> bool {
83            self.pos == self.cap
84        }
85
86        fn as_slice(&self) -> &[u8] {
87            &self.buf[self.pos..self.cap]
88        }
89    }
90
91    impl<'i> BufReader<'i> {
92        pub fn peek_byte(&self) -> Option<u8> {
93            let s = self.as_slice();
94            s.first().copied()
95        }
96
97        pub fn copy_to_slice<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
98            let mut output_pos = 0;
99
100            while output_pos < buf.len() {
101                if self.is_empty() {
102                    self.fill_buffer()?;
103                }
104
105                let available = &self.buf[self.pos..self.cap];
106                let window_len = (buf.len() - output_pos).min(available.len());
107                let window = &mut buf[output_pos..output_pos + window_len];
108
109                window.copy_from_slice(&available[..window_len]);
110                self.pos += window_len;
111                output_pos += window_len;
112            }
113
114            if self.is_empty() && self.decoder.remaining_len() != 0 {
116                self.fill_buffer()?
117            }
118
119            debug_assert_eq!(output_pos, buf.len());
120
121            Ok(buf)
122        }
123    }
124}
125
126#[cfg(feature = "pem")]
128#[derive(Clone)]
129pub struct PemReader<'i> {
130    reader: RefCell<utils::BufReader<'i>>,
132
133    input_len: Length,
135
136    position: Length,
138}
139
140#[cfg(feature = "pem")]
141impl<'i> PemReader<'i> {
142    pub fn new(pem: &'i [u8]) -> Result<Self> {
146        let reader = utils::BufReader::new(pem)?;
147        let input_len = Length::try_from(reader.remaining_len())?;
148
149        Ok(Self {
150            reader: RefCell::new(reader),
151            input_len,
152            position: Length::ZERO,
153        })
154    }
155
156    pub fn type_label(&self) -> &'i str {
159        self.reader.borrow().type_label()
160    }
161}
162
163#[cfg(feature = "pem")]
164impl<'i> Reader<'i> for PemReader<'i> {
165    fn input_len(&self) -> Length {
166        self.input_len
167    }
168
169    fn peek_byte(&self) -> Option<u8> {
170        if self.is_finished() {
171            None
172        } else {
173            self.reader.borrow().peek_byte()
174        }
175    }
176
177    fn peek_header(&self) -> Result<Header> {
178        if self.is_finished() {
179            Err(Error::incomplete(self.offset()))
180        } else {
181            Header::decode(&mut self.clone())
182        }
183    }
184
185    fn position(&self) -> Length {
186        self.position
187    }
188
189    fn read_slice(&mut self, _len: Length) -> Result<&'i [u8]> {
190        Err(ErrorKind::Reader.into())
192    }
193
194    fn read_into<'o>(&mut self, buf: &'o mut [u8]) -> Result<&'o [u8]> {
195        let bytes = self.reader.borrow_mut().copy_to_slice(buf)?;
196
197        self.position = (self.position + bytes.len())?;
198
199        debug_assert_eq!(
200            self.position,
201            (self.input_len - Length::try_from(self.reader.borrow().remaining_len())?)?
202        );
203
204        Ok(bytes)
205    }
206}