asn1_codecs/per/common/decode/
mod.rs

1//! Decode APIs for APER Codec
2
3mod decode_internal;
4
5use bitvec::prelude::*;
6
7use crate::{PerCodecData, PerCodecError, PerCodecErrorCause};
8
9use std::convert::TryFrom;
10
11#[allow(unused)]
12use decode_internal::*;
13
14pub(crate) use decode_internal::decode_length_determinent_common;
15
16// Common decode functions used by the API functions of the codec. The API functions call the
17// common functions For example, `decode_choice_idx` API will call `decode_choice_idx_common` fro
18// APER Codec by passing aligned as `true`.
19
20// Common decode function for choice index
21pub fn decode_choice_idx_common(
22    data: &mut PerCodecData,
23    lb: i128,
24    ub: i128,
25    is_extensible: bool,
26    aligned: bool,
27) -> Result<(i128, bool), PerCodecError> {
28    let (idx, extended) = if is_extensible {
29        let extended = data.decode_bool()?;
30        if !extended {
31            let (idx, _) = decode_integer_common(data, Some(lb), Some(ub), false, aligned)?;
32            (idx, extended)
33        } else {
34            let idx = decode_normally_small_non_negative_whole_number_common(data, aligned)?;
35            (idx, extended)
36        }
37    } else {
38        let (idx, _) = decode_integer_common(data, Some(lb), Some(ub), false, aligned)?;
39        (idx, false)
40    };
41
42    data.dump();
43
44    Ok((idx, extended))
45}
46
47// Common decode function for sequence header.
48pub fn decode_sequence_header_common(
49    data: &mut PerCodecData,
50    is_extensible: bool,
51    optional_count: usize,
52    _aligned: bool,
53) -> Result<(BitVec<u8, Msb0>, bool), PerCodecError> {
54    let extended = if is_extensible {
55        data.decode_bool()?
56    } else {
57        false
58    };
59
60    let mut bitmap = BitVec::new();
61    if optional_count > 0 {
62        log::trace!("{:?} optionals found", optional_count);
63        bitmap.extend(data.get_bitvec(optional_count)?);
64    }
65    data.dump();
66    Ok((bitmap, extended))
67}
68
69// Common extensions skip
70pub fn decode_sequence_extensions_skip_bits(
71    data: &mut PerCodecData,
72    aligned: bool,
73) -> Result<(), PerCodecError> {
74    log::warn!("Skipping Extensions Decoding....");
75    let bitmap_length = decode_length_determinent_common(data, None, None, true, aligned)?;
76    log::trace!("Found a bitmap of '{}' extensions.", bitmap_length);
77
78    let mut bitmap: BitVec<u8, Msb0> = BitVec::new();
79    if bitmap_length > 0 {
80        bitmap.extend(data.get_bitvec(bitmap_length)?);
81
82        let present_extensions = bitmap.iter_ones().len();
83        log::trace!("Present extensions: {}", present_extensions);
84        let mut extension_no = 0;
85        while present_extensions > extension_no {
86            extension_no += 1;
87            let octets = decode_length_determinent_common(data, None, None, false, aligned)?;
88            log::trace!(
89                "Extension #: {}, Open Type Encoded in '{}' Octets",
90                extension_no,
91                octets
92            );
93            data.advance_maybe_err(octets * 8, false)?;
94        }
95        log::warn!("Skipped decoding {} Extensions.", present_extensions);
96        Ok(())
97    } else {
98        Err(PerCodecError::new(
99            PerCodecErrorCause::Generic,
100            "Extension Bit set, but extensions length zero!",
101        ))
102    }
103}
104
105// Common function to decode INTEGER.
106pub fn decode_integer_common(
107    data: &mut PerCodecData,
108    lb: Option<i128>,
109    ub: Option<i128>,
110    is_extensible: bool,
111    aligned: bool,
112) -> Result<(i128, bool), PerCodecError> {
113    let extended_value = if is_extensible {
114        data.decode_bool()?
115    } else {
116        false
117    };
118
119    let value = if extended_value {
120        // 12.1
121        decode_unconstrained_whole_number_common(data, aligned)?
122    } else {
123        // 12.2
124        match lb {
125            None =>
126            // 12.2.4
127            {
128                decode_unconstrained_whole_number_common(data, aligned)?
129            }
130            Some(lb) => {
131                match ub {
132                    None =>
133                    // 12.2.3
134                    {
135                        decode_semi_constrained_whole_number_common(data, lb, aligned)?
136                    }
137                    Some(ub) => {
138                        // 12.2.1 and 12.2.2
139                        decode_constrained_whole_number_common(data, lb, ub, aligned)?
140                    }
141                }
142            }
143        }
144    };
145
146    data.dump();
147
148    Ok((value, extended_value))
149}
150
151// Common function to decode a REAL value
152pub(crate) fn decode_real_common(
153    data: &mut PerCodecData,
154    aligned: bool,
155) -> Result<f64, PerCodecError> {
156    // ITU X.691 section 15 notes that this value starts with a length
157    // determinant. For now, UPER and APER are identical other than
158    // determining alignment for the length determinant.
159    let length = decode_length_determinent_common(data, None, None, false, aligned)?;
160    let decoded_value: f64;
161
162    // ITU X.691 section 15 largely refers to ITU X.690 section 8.5 for REAL
163    // encoding and decoding.
164    if length == 0 {
165        // ITU X.690 section 8.5.2: if there is no content, then return +0.
166        decoded_value = 0.;
167    } else {
168        let first_byte = data.decode_bits_as_integer(8, false)?;
169        if let Ok(first_byte) = u8::try_from(first_byte) {
170            // ITU X.690 section 8.5.6: determine whether this is a special
171            // value. If not, figure out which base this is encoded with.
172            // Section 8.5.9 covers special values, section 8.5.7 covers
173            // binary encoding of base 2/8/16, and section 8.5.8 covers
174            // ISO 6093 encoding of base 10 values.
175            match first_byte {
176                super::NEGATIVE_ZERO => {
177                    decoded_value = -0.;
178                }
179                super::INFINITY => {
180                    decoded_value = f64::INFINITY;
181                }
182                super::NEGATIVE_INFINITY => {
183                    decoded_value = f64::NEG_INFINITY;
184                }
185                super::NOT_A_NUMBER => {
186                    decoded_value = f64::NAN;
187                }
188                super::BASE_10_NR1 | super::BASE_10_NR2 | super::BASE_10_NR3 => {
189                    // Subtract 1 from length, since first byte was metadata.
190                    // We currently decode ISO 6093 NR1, NR2, and NR3 all using
191                    // the same underlying approach.
192                    log::trace!(
193                        "Decoding REAL as a base 10 value using ISO 6093 with {} bytes",
194                        length - 1
195                    );
196                    decoded_value = decode_real_as_decimal(data, length - 1)?;
197                }
198                first_byte => {
199                    if real_uses_binary(first_byte) {
200                        // Subtract 1 from length, since first byte was metadata.
201                        // We currently decode base 2, base 8, and base 16 all
202                        // using the same underlying approach.
203                        log::trace!("Decoding REAL as a binary value with {} bytes", length - 1);
204                        decoded_value = decode_real_as_binary(first_byte, data, length - 1)?;
205                    } else {
206                        // TODO: Change cause to InvalidValue once it is supported
207                        return Err(PerCodecError::new(
208                            PerCodecErrorCause::Generic,
209                            format!(
210                                "Can only decode REAL values with reserved values, binary-encoded values, or base 10 values (encoded first byte: {:b})",
211                                first_byte
212                            )
213                        ));
214                    }
215                }
216            }
217        } else {
218            return Err(PerCodecError::new(
219                PerCodecErrorCause::Generic,
220                "Could not convert i128 with 8 data bits into a u8; please contact the developers",
221            ));
222        }
223    }
224
225    data.dump();
226    Ok(decoded_value)
227}
228
229// Common function to decode a Boolean
230pub fn decode_bool_common(data: &mut PerCodecData, _aligned: bool) -> Result<bool, PerCodecError> {
231    let result = data.decode_bool()?;
232
233    data.dump();
234
235    Ok(result)
236}
237
238// Common function to decode an Enumerated Value
239pub fn decode_enumerated_common(
240    data: &mut PerCodecData,
241    lb: Option<i128>,
242    ub: Option<i128>,
243    is_extensible: bool,
244    aligned: bool,
245) -> Result<(i128, bool), PerCodecError> {
246    log::trace!(
247        "decode_enumerated: lb: {:?}, ub: {:?}, is_extensible: {}",
248        lb,
249        ub,
250        is_extensible
251    );
252
253    let is_extended = if is_extensible {
254        data.decode_bool()?
255    } else {
256        false
257    };
258
259    let decoded = if !is_extended {
260        let decoded = decode_integer_common(data, lb, ub, false, aligned)?;
261        decoded.0
262    } else {
263        decode_normally_small_non_negative_whole_number_common(data, aligned)?
264    };
265
266    data.dump();
267
268    Ok((decoded, is_extended))
269}
270
271// Common function to decode a Bit String
272pub fn decode_bitstring_common(
273    data: &mut PerCodecData,
274    lb: Option<i128>,
275    ub: Option<i128>,
276    is_extensible: bool,
277    aligned: bool,
278) -> Result<BitVec<u8, Msb0>, PerCodecError> {
279    let is_extended = if is_extensible {
280        data.decode_bool()?
281    } else {
282        false
283    };
284
285    let mut bv = BitVec::new();
286    loop {
287        let length = if is_extended {
288            decode_length_determinent_common(data, None, None, false, aligned)?
289        } else {
290            decode_length_determinent_common(data, lb, ub, false, aligned)?
291        };
292
293        if length > 0 {
294            if length > 16 && aligned {
295                data.decode_align()?;
296            }
297            bv.extend(data.get_bitvec(length)?);
298        }
299
300        // Fragmented So get the chunks in multiples of 16384,
301        if length >= 16384 {
302            continue;
303        } else {
304            break;
305        }
306    }
307
308    data.dump();
309
310    Ok(bv)
311}
312
313// Common function to decode an OCTET STRING
314pub fn decode_octetstring_common(
315    data: &mut PerCodecData,
316    lb: Option<i128>,
317    ub: Option<i128>,
318    is_extensible: bool,
319    aligned: bool,
320) -> Result<Vec<u8>, PerCodecError> {
321    log::trace!(
322        "decode_bitstring: lb: {:?}, ub: {:?}, is_extensible: {}",
323        lb,
324        ub,
325        is_extensible
326    );
327
328    let is_extended = if is_extensible {
329        data.decode_bool()?
330    } else {
331        false
332    };
333
334    let mut octets = Vec::new();
335    loop {
336        let length = if is_extended {
337            decode_length_determinent_common(data, None, None, false, aligned)?
338        } else {
339            decode_length_determinent_common(data, lb, ub, false, aligned)?
340        };
341
342        if length > 0 {
343            if length > 2 && aligned {
344                data.decode_align()?;
345            }
346            octets.extend(data.get_bytes(length)?);
347        }
348
349        // Fragmented So get the chunks in multiples of 16384,
350        if length >= 16384 {
351            continue;
352        } else {
353            break;
354        }
355    }
356
357    data.dump();
358
359    Ok(octets)
360}
361
362pub(crate) fn decode_string_common(
363    data: &mut PerCodecData,
364    lb: Option<i128>,
365    ub: Option<i128>,
366    is_extensible: bool,
367    bits_per_char: usize,
368    aligned: bool,
369) -> Result<String, PerCodecError> {
370    let is_extended = if is_extensible {
371        data.decode_bool()?
372    } else {
373        false
374    };
375
376    let length = if is_extended {
377        decode_length_determinent_common(data, None, None, false, aligned)?
378    } else {
379        decode_length_determinent_common(data, lb, ub, false, aligned)?
380    };
381
382    let length = length * bits_per_char;
383    if length > 16 && aligned {
384        data.decode_align()?;
385    }
386    let bits = data.get_bitvec(length)?;
387    let bytes = bits
388        .chunks_exact(bits_per_char)
389        .map(|c| {
390            let mut v = c.to_bitvec();
391            let howmany = 8 - bits_per_char;
392            for _ in 0..howmany {
393                v.insert(0, false);
394            }
395            v.load_be::<u8>()
396        })
397        .collect::<Vec<u8>>();
398
399    data.dump();
400
401    std::str::from_utf8(&bytes)
402        .map(|s| s.to_string())
403        .map_err(|_| PerCodecError::new(PerCodecErrorCause::Generic, "UTF decode failed"))
404}
405
406#[cfg(test)]
407mod tests {
408
409    use super::*;
410
411    #[test]
412    fn test_decode_real_base_2() {
413        let data = &[0x03, 0x80, 0xFB, 0x05];
414        let mut codec_data = PerCodecData::from_slice_aper(data);
415        let value = decode_real_common(&mut codec_data, true);
416        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
417        let value = value.unwrap();
418        assert_eq!(value, 0.15625);
419    }
420
421    #[test]
422    fn test_decode_real_base_8() {
423        let data = &[0x03, 0x90, 0xFE, 0x0A];
424        let mut codec_data = PerCodecData::from_slice_aper(data);
425        let value = decode_real_common(&mut codec_data, true);
426        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
427        let value = value.unwrap();
428        assert_eq!(value, 0.15625);
429    }
430
431    #[test]
432    fn test_decode_real_base_16() {
433        let data = &[0x03, 0xAC, 0xFE, 0x05];
434        let mut codec_data = PerCodecData::from_slice_aper(data);
435        let value = decode_real_common(&mut codec_data, true);
436        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
437        let value = value.unwrap();
438        assert_eq!(value, 0.15625);
439    }
440
441    #[test]
442    fn test_decode_real_base_10_nr1() {
443        let data = &[0x04, super::super::BASE_10_NR1, b'1', b'2', b'3'];
444        let mut codec_data = PerCodecData::from_slice_aper(data);
445        let value = decode_real_common(&mut codec_data, true);
446        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
447        let value = value.unwrap();
448        assert_eq!(value, 123.0f64);
449    }
450
451    #[test]
452    fn test_decode_real_base_10_nr2() {
453        let data = &[
454            0x08,
455            super::super::BASE_10_NR2,
456            b'0',
457            b'.',
458            b'1',
459            b'5',
460            b'6',
461            b'2',
462            b'5',
463        ];
464        let mut codec_data = PerCodecData::from_slice_aper(data);
465        let value = decode_real_common(&mut codec_data, true);
466        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
467        let value = value.unwrap();
468        assert_eq!(value, 0.15625);
469    }
470
471    #[test]
472    fn test_decode_real_base_10_nr3() {
473        let data = &[
474            0x0A,
475            super::super::BASE_10_NR2,
476            b'1',
477            b'.',
478            b'5',
479            b'6',
480            b'2',
481            b'5',
482            b'e',
483            b'-',
484            b'1',
485        ];
486        let mut codec_data = PerCodecData::from_slice_aper(data);
487        let value = decode_real_common(&mut codec_data, true);
488        assert!(value.is_ok(), "{:#?}", value.err().unwrap());
489        let value = value.unwrap();
490        assert_eq!(value, 0.15625);
491    }
492}