asn1_cereal/ber/stream.rs
1//! A `SAXParser` inspired stream parser and encoder for ber streams.
2//!
3//! Given a struct that implements `StreamDecodee`, a `StreamDecoder` can be used to
4//! decode the stream, calling each function in the `StreamDecodee` trait as they
5//! are encountered.
6//!
7//! The `StreamEncoder` struct is also provided, which itself implements the
8//! `StreamDecodee` trait. This allows you to encode an ASN.1 stream using
9//! the `StreamDecodee` interface as the caller.
10
11use tag;
12use err;
13use byte;
14
15use std::cmp::Ordering;
16use std::io;
17
18/// This trait provides a `SAXParser` inspired interface for parsing ASN.1 streams.
19///
20/// If it were implemented, the `ParseResult` return types would be used to
21/// provide feedback on whether parsing of that element was successful.
22pub trait StreamDecodee {
23 /// This function is called when an ASN.1 tag is encountered. In other
24 /// words, at the start of an ASN.1 element.
25 fn start_element(&mut self, _: tag::Tag, _: tag::Len) -> ParseResult {
26 ParseResult::Ok
27 }
28
29 /// This function is called when an ASN.1 element has finished decoding.
30 /// Note that this is also called for all elements, even after a primitive()
31 /// call. For this reason, you may need to check the constructed flag in some
32 /// cases.
33 fn end_element(&mut self, _: tag::Tag, _: tag::Len) -> ParseResult {
34 ParseResult::Ok
35 }
36
37 // FIXME: Currently it's the function's responsibility to decode the element
38 // with the correct amounts of bytes. Without heap allocation, this might be
39 // the only way.
40 /// This function is called when a primitive element is encountered. Note that both
41 /// start_element and end_element are called before/after this function.
42 fn primitive<I: Iterator<Item=io::Result<u8>>>(&mut self, reader: &mut byte::ByteReader<I>,
43 len: tag::LenNum) -> ParseResult {
44 for _ in 0..len {
45 if let Err(e) = reader.read() {
46 return e.into();
47 }
48 }
49 ParseResult::Ok
50 }
51
52 /// This function would be called when a recoverable decode error occurs, however
53 /// currently nothing calls this.
54 fn warning(_: err::DecodeError) -> ParseResult {
55 ParseResult::Stop
56 }
57
58 /// This function would be called when a fatal decoding error occurs, however
59 /// currently nothing calls this.
60 fn error(_: err::DecodeError) {
61 }
62}
63
64/// A decoder that calls into a struct implementing the `StreamDecodee` trait,
65/// similar to a `SAXParser`.
66pub struct StreamDecoder<'a, I: Iterator<Item=io::Result<u8>>, S: StreamDecodee + 'a> {
67 /// Internal reader with an included byte counter.
68 reader: byte::ByteReader<I>,
69 /// Object implementing StreamDecodee trait, functions are called when
70 /// specific things are found in the ASN.1 stream.
71 decodee: &'a mut S,
72}
73
74impl<'a, I: Iterator<Item=io::Result<u8>>, S: StreamDecodee> StreamDecoder<'a, I, S> {
75 pub fn new<R: Into<byte::ByteReader<I>>>(reader: R, decodee: &'a mut S) -> Self {
76 StreamDecoder {
77 reader: reader.into(),
78 decodee: decodee,
79 }
80 }
81
82 /// Decode an asn1 element.
83 pub fn decode(&mut self) -> Result<(), err::DecodeError> {
84 self._decode().and(Ok(()))
85 }
86
87 // FIXME: Convert explicit decoded_len to use diff of internal reader count.
88 /// Internal decode function.
89 fn _decode(&mut self) -> Result<(tag::Tag, tag::Len), err::DecodeError> {
90 // Decode tag.
91 let (tag, len) = try!(tag::read_taglen(&mut self.reader));
92 let post_tag_count: tag::LenNum = self.reader.count;
93
94 // Call the decodee start element callback;
95 self.decodee.start_element(tag, len);
96
97
98 // If this type is constructed, decode child element..
99 if tag.constructed {
100 // Loop over child elements.
101 loop {
102 let decoded_len = self.reader.count - post_tag_count;
103 // Compare decoded length with length in tag.
104 // Put this first to handle zero-length elements.
105 match len.partial_cmp(&decoded_len) {
106 // Return an error when we've decoded too much.
107 Some(Ordering::Less) => return Err(err::DecodeError::GreaterLen),
108 // Finish loop when equal, we must be finished.
109 Some(Ordering::Equal) => break,
110 // Continue when we are still decoding, or using indefinite
111 // length encoding.
112 Some(Ordering::Greater) | None => {},
113 };
114
115 // Decode each child element.
116 let (child_tag, child_len) = try!(self._decode());
117
118 // If applicable, identify end of indefinite length encoding.
119 // When decoding indefinite length encoding, stop on '00 00'
120 // tag.
121 if child_len == tag::Len::Def(0) &&
122 child_tag.class == tag::Class::Universal &&
123 child_tag.tagnum == 0 {
124 break;
125 }
126 }
127 // Otherwise decode primitive value.
128 } else {
129 let len_num = try!(match len {
130 tag::Len::Def(l) => Ok(l),
131 tag::Len::Indef =>
132 Err(err::DecodeError::PrimIndef),
133 });
134
135 // Call decodee primitive decode callback.
136 self.decodee.primitive(&mut self.reader, len_num);
137
138 // Calculate decoded length.
139 let decoded_len = self.reader.count - post_tag_count;
140 // Ensure the exact amout of bytes was decoded.
141 match len.partial_cmp(&decoded_len) {
142 Some(Ordering::Less) => return Err(err::DecodeError::GreaterLen),
143 Some(Ordering::Greater) => return Err(err::DecodeError::SmallerLen),
144 _ => {},
145 }
146 }
147
148 // Call decodee end element callback.
149 self.decodee.end_element(tag, len);
150
151 // Return decoded + tag_len, which is total decoded length.
152 Ok((tag, len))
153 }
154}
155
156/// A stream encoder that implements `StreamDecodee`. Using this,
157/// a ASN.1 stream can be written using a `SAXParser` style interface.
158pub struct StreamEncoder<W: io::Write> {
159 writer: byte::ByteWriter<W>
160}
161
162impl<W: io::Write> StreamEncoder<W> {
163 pub fn new<T: Into<byte::ByteWriter<W>>>(writer: T) -> Self {
164 StreamEncoder {
165 writer: writer.into(),
166 }
167 }
168}
169
170impl<W: io::Write> StreamDecodee for StreamEncoder<W> {
171 fn start_element(&mut self, tag: tag::Tag, len: tag::Len) -> ParseResult {
172 if let Err(e) = tag::write_taglen(tag, len, &mut self.writer) {
173 e.into()
174 } else {
175 ParseResult::Ok
176 }
177 }
178
179 fn end_element(&mut self, _: tag::Tag, _: tag::Len) -> ParseResult {
180 ParseResult::Ok
181 }
182
183 fn primitive<I: Iterator<Item=io::Result<u8>>>(&mut self, reader: &mut byte::ByteReader<I>,
184 len: tag::LenNum) -> ParseResult {
185 for _ in 0..len {
186 // Read a byte and write a byte.
187 match reader.read() {
188 Ok(byte) => if let Err(e) = self.writer.write_byte(byte) {
189 return e.into()
190 },
191 Err(e) => return e.into(),
192 };
193 }
194 ParseResult::Ok
195 }
196}
197
198
199// FIXME: This seems to have two mixed meanings, perhaps split it?
200/// The result of parsing after a callback on a `StreamDecodee`.
201///
202/// If it were implemented, this would provide feedback to the Decoder/Parser.
203pub enum ParseResult {
204 /// Everything went okay.
205 Ok,
206 /// Decoding should stop.
207 Stop,
208 /// Decoding should skip next element.
209 Skip,
210 /// An error occured decoding an element.
211 DecodeError(err::DecodeError),
212 /// An error occured encoding an element.
213 EncodeError(err::EncodeError),
214 /// An IO error occured.
215 IO(io::Error),
216}
217
218impl From<err::DecodeError> for ParseResult {
219 fn from(err: err::DecodeError) -> Self {
220 ParseResult::DecodeError(err)
221 }
222}
223
224impl From<err::EncodeError> for ParseResult {
225 fn from(err: err::EncodeError) -> Self {
226 ParseResult::EncodeError(err)
227 }
228}
229
230impl From<io::Error> for ParseResult {
231 fn from(err: io::Error) -> Self {
232 ParseResult::IO(err)
233 }
234}