asn1_der/
data.rs

1use crate::{error::ErrorChain, Asn1DerError};
2use core::{iter, slice};
3
4/// A trait defining a byte source
5pub trait Source: Sized {
6    /// Reads the next element
7    fn read(&mut self) -> Result<u8, Asn1DerError>;
8
9    /// Creates a counting source
10    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
11    fn counting_source(self, ctr: &mut usize) -> CountingSource<Self> {
12        CountingSource { source: self, ctr }
13    }
14    /// Creates a copying source
15    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
16    fn copying_source<U: Sink>(self, sink: U) -> CopyingSource<Self, U> {
17        CopyingSource { source: self, sink }
18    }
19}
20impl<S: Source> Source for &mut S {
21    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
22    fn read(&mut self) -> Result<u8, Asn1DerError> {
23        (*self).read()
24    }
25}
26impl<'a> Source for slice::Iter<'a, u8> {
27    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
28    fn read(&mut self) -> Result<u8, Asn1DerError> {
29        match self.next() {
30            Some(e) => Ok(*e),
31            None => Err(eio!("Cannot read beyond end of slice-iterator")),
32        }
33    }
34}
35impl<'a, A: Iterator<Item = &'a u8>, B: Iterator<Item = &'a u8>> Source for iter::Chain<A, B> {
36    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
37    fn read(&mut self) -> Result<u8, Asn1DerError> {
38        match self.next() {
39            Some(e) => Ok(*e),
40            None => Err(eio!("Cannot read beyond end of chain-iterator")),
41        }
42    }
43}
44impl<'a, I: Iterator<Item = &'a u8> + 'a> Source for iter::Skip<I> {
45    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
46    fn read(&mut self) -> Result<u8, Asn1DerError> {
47        match self.next() {
48            Some(e) => Ok(*e),
49            None => Err(eio!("Cannot read beyond end of chain-iterator")),
50        }
51    }
52}
53
54/// A source that counts the amount of elements read
55///
56/// __Warning: if a call to `read` would cause `ctr` to exceed `usize::max_value()`, this source
57/// will return an error and the element that has been read from the underlying source will be
58/// lost__
59pub struct CountingSource<'a, S: Source> {
60    source: S,
61    ctr: &'a mut usize,
62}
63impl<'a, S: Source> Source for CountingSource<'a, S> {
64    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
65    fn read(&mut self) -> Result<u8, Asn1DerError> {
66        let e = self.source.read().propagate(e!("Failed to read element from underlying source"))?;
67        match self.ctr.checked_add(1) {
68            Some(ctr_next) => {
69                *self.ctr = ctr_next;
70                Ok(e)
71            }
72            _ => Err(eio!("Cannot read more because the position counter would overflow")),
73        }
74    }
75}
76
77/// A source that also copies each read element to the `sink`
78///
79/// __Warning: if a call to `write` fails, this source will return an error and the element that has
80/// been read from the underlying source will be lost__
81pub struct CopyingSource<S: Source, U: Sink> {
82    source: S,
83    sink: U,
84}
85impl<S: Source, U: Sink> CopyingSource<S, U> {
86    /// Copies the next element
87    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
88    pub fn copy_next(&mut self) -> Result<(), Asn1DerError> {
89        self.read()?;
90        Ok(())
91    }
92    /// Copies the next `n` elements
93    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
94    pub fn copy_n(&mut self, n: usize) -> Result<(), Asn1DerError> {
95        (0..n).try_for_each(|_| self.copy_next())
96    }
97}
98impl<S: Source, U: Sink> Source for CopyingSource<S, U> {
99    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
100    fn read(&mut self) -> Result<u8, Asn1DerError> {
101        let e = self.source.read().propagate(e!("Failed to read element from underlying source"))?;
102        self.sink.write(e).propagate(e!("Failed to copy element to sink"))?;
103        Ok(e)
104    }
105}
106
107/// A trait defining a byte sink
108pub trait Sink: Sized {
109    /// Writes `e` to `self`
110    fn write(&mut self, e: u8) -> Result<(), Asn1DerError>;
111    /// Creates a counting sink
112    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
113    fn counting_sink(self, ctr: &mut usize) -> CountingSink<Self> {
114        CountingSink { sink: self, ctr }
115    }
116}
117impl<S: Sink> Sink for &mut S {
118    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
119    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
120        (*self).write(e)
121    }
122}
123impl<'a> Sink for slice::IterMut<'a, u8> {
124    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
125    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
126        match self.next() {
127            Some(t) => {
128                *t = e;
129                Ok(())
130            }
131            None => Err(eio!("Cannot write beyond end of slice-iterator")),
132        }
133    }
134}
135#[cfg(all(feature = "std", not(feature = "no_panic")))]
136impl Sink for Vec<u8> {
137    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
138        self.push(e);
139        Ok(())
140    }
141}
142
143/// A sink that counts the amount of elements written
144///
145/// __Warning: if a call to `write` would cause `ctr` to exceed `usize::max_value()`, this sink
146/// will return an error but the element is written nonetheless__
147pub struct CountingSink<'a, S: Sink> {
148    sink: S,
149    ctr: &'a mut usize,
150}
151impl<'a, S: Sink> Sink for CountingSink<'a, S> {
152    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
153    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
154        self.sink.write(e).propagate(e!("Failed to write element to underlying source"))?;
155        *self.ctr = match self.ctr.checked_add(1) {
156            Some(ctr_next) => ctr_next,
157            None => Err(eio!("Cannot write more because the position counter would overflow"))?,
158        };
159        Ok(())
160    }
161}
162
163/// A slice-backed sink
164pub struct SliceSink<'a> {
165    slice: &'a mut [u8],
166    pos: &'a mut usize,
167}
168impl<'a> SliceSink<'a> {
169    /// Creates a new `SliceSink` with `slice` as backing and `pos` as position counter
170    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
171    pub fn new(slice: &'a mut [u8], pos: &'a mut usize) -> Self {
172        Self { slice, pos }
173    }
174}
175impl<'a> Sink for SliceSink<'a> {
176    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
177    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
178        match self.slice.get_mut(*self.pos) {
179            Some(t) => match self.pos.checked_add(1) {
180                Some(pos_next) => {
181                    *self.pos = pos_next;
182                    *t = e;
183                    Ok(())
184                }
185                None => Err(eio!("Cannot write more because the position counter would overflow"))?,
186            },
187            None => Err(eio!("Cannot write beyond the end-of-slice"))?,
188        }
189    }
190}
191impl<'a> From<SliceSink<'a>> for &'a [u8] {
192    #[cfg_attr(feature = "no_panic", no_panic::no_panic)]
193    fn from(sink: SliceSink<'a>) -> Self {
194        match sink.slice.len() {
195            len if *sink.pos < len => &sink.slice[..*sink.pos],
196            _ => sink.slice,
197        }
198    }
199}
200
201/// A newtype wrapper around a `&'a mut Vec<u8>` that implements `Sink` and `Into<&'a [u8]>`
202#[cfg(all(feature = "std", not(feature = "no_panic")))]
203pub struct VecBacking<'a>(pub &'a mut Vec<u8>);
204#[cfg(all(feature = "std", not(feature = "no_panic")))]
205impl<'a> Sink for VecBacking<'a> {
206    fn write(&mut self, e: u8) -> Result<(), Asn1DerError> {
207        self.0.push(e);
208        Ok(())
209    }
210}
211#[cfg(all(feature = "std", not(feature = "no_panic")))]
212impl<'a> From<VecBacking<'a>> for &'a [u8] {
213    fn from(backing: VecBacking<'a>) -> &'a [u8] {
214        backing.0.as_slice()
215    }
216}