der/asn1/
real.rs

1//! ASN.1 `REAL` support.
2
3// TODO(tarcieri): checked arithmetic
4#![allow(
5    clippy::cast_lossless,
6    clippy::cast_sign_loss,
7    clippy::integer_arithmetic
8)]
9
10use crate::{
11    BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, StrRef, Tag,
12    Writer,
13};
14
15use super::integer::uint::strip_leading_zeroes;
16
17impl<'a> DecodeValue<'a> for f64 {
18    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
19        let bytes = BytesRef::decode_value(reader, header)?.as_slice();
20
21        if header.length == Length::ZERO {
22            Ok(0.0)
23        } else if is_nth_bit_one::<7>(bytes) {
24            // Binary encoding from section 8.5.7 applies
25            let sign: u64 = u64::from(is_nth_bit_one::<6>(bytes));
26
27            // Section 8.5.7.2: Check the base -- the DER specs say that only base 2 should be supported in DER
28            let base = mnth_bits_to_u8::<5, 4>(bytes);
29
30            if base != 0 {
31                // Real related error: base is not DER compliant (base encoded in enum)
32                return Err(Tag::Real.value_error());
33            }
34
35            // Section 8.5.7.3
36            let scaling_factor = mnth_bits_to_u8::<3, 2>(bytes);
37
38            // Section 8.5.7.4
39            let mantissa_start;
40            let exponent = match mnth_bits_to_u8::<1, 0>(bytes) {
41                0 => {
42                    mantissa_start = 2;
43                    let ebytes = (i16::from_be_bytes([0x0, bytes[1]])).to_be_bytes();
44                    u64::from_be_bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ebytes[0], ebytes[1]])
45                }
46                1 => {
47                    mantissa_start = 3;
48                    let ebytes = (i16::from_be_bytes([bytes[1], bytes[2]])).to_be_bytes();
49                    u64::from_be_bytes([0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ebytes[0], ebytes[1]])
50                }
51                _ => {
52                    // Real related error: encoded exponent cannot be represented on an IEEE-754 double
53                    return Err(Tag::Real.value_error());
54                }
55            };
56            // Section 8.5.7.5: Read the remaining bytes for the mantissa
57            let mut n_bytes = [0x0; 8];
58            for (pos, byte) in bytes[mantissa_start..].iter().rev().enumerate() {
59                n_bytes[7 - pos] = *byte;
60            }
61            let n = u64::from_be_bytes(n_bytes);
62            // Multiply byt 2^F corresponds to just a left shift
63            let mantissa = n << scaling_factor;
64            // Create the f64
65            Ok(encode_f64(sign, exponent, mantissa))
66        } else if is_nth_bit_one::<6>(bytes) {
67            // This either a special value, or it's the value minus zero is encoded, section 8.5.9 applies
68            match mnth_bits_to_u8::<1, 0>(bytes) {
69                0 => Ok(f64::INFINITY),
70                1 => Ok(f64::NEG_INFINITY),
71                2 => Ok(f64::NAN),
72                3 => Ok(-0.0_f64),
73                _ => Err(Tag::Real.value_error()),
74            }
75        } else {
76            let astr = StrRef::from_bytes(&bytes[1..])?;
77            match astr.inner.parse::<f64>() {
78                Ok(val) => Ok(val),
79                // Real related error: encoding not supported or malformed
80                Err(_) => Err(Tag::Real.value_error()),
81            }
82        }
83    }
84}
85
86impl EncodeValue for f64 {
87    fn value_len(&self) -> Result<Length> {
88        if self.is_sign_positive() && (*self) < f64::MIN_POSITIVE {
89            // Zero: positive yet smaller than the minimum positive number
90            Ok(Length::ZERO)
91        } else if self.is_nan()
92            || self.is_infinite()
93            || (self.is_sign_negative() && -self < f64::MIN_POSITIVE)
94        {
95            // NaN, infinite (positive or negative), or negative zero (negative but its negative is less than the min positive number)
96            Ok(Length::ONE)
97        } else {
98            // The length is that of the first octets plus those needed for the exponent plus those needed for the mantissa
99            let (_sign, exponent, mantissa) = decode_f64(*self);
100
101            let exponent_len = if exponent == 0 {
102                // Section 8.5.7.4: there must be at least one octet for exponent encoding
103                // But, if the exponent is zero, it'll be skipped, so we make sure force it to 1
104                Length::ONE
105            } else {
106                let ebytes = exponent.to_be_bytes();
107                Length::try_from(strip_leading_zeroes(&ebytes).len())?
108            };
109
110            let mantissa_len = if mantissa == 0 {
111                Length::ONE
112            } else {
113                let mbytes = mantissa.to_be_bytes();
114                Length::try_from(strip_leading_zeroes(&mbytes).len())?
115            };
116
117            exponent_len + mantissa_len + Length::ONE
118        }
119    }
120
121    fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
122        // Check if special value
123        // Encode zero first, if it's zero
124        // Special value from section 8.5.9 if non zero
125        if self.is_nan()
126            || self.is_infinite()
127            || (self.is_sign_negative() && -self < f64::MIN_POSITIVE)
128            || (self.is_sign_positive() && (*self) < f64::MIN_POSITIVE)
129        {
130            if self.is_sign_positive() && (*self) < f64::MIN_POSITIVE {
131                // Zero
132                return Ok(());
133            } else if self.is_nan() {
134                // Not a number
135                writer.write_byte(0b0100_0010)?;
136            } else if self.is_infinite() {
137                if self.is_sign_negative() {
138                    // Negative infinity
139                    writer.write_byte(0b0100_0001)?;
140                } else {
141                    // Plus infinity
142                    writer.write_byte(0b0100_0000)?;
143                }
144            } else {
145                // Minus zero
146                writer.write_byte(0b0100_0011)?;
147            }
148        } else {
149            // Always use binary encoding, set bit 8 to 1
150            let mut first_byte = 0b1000_0000;
151
152            if self.is_sign_negative() {
153                // Section 8.5.7.1: set bit 7 to 1 if negative
154                first_byte |= 0b0100_0000;
155            }
156
157            // Bits 6 and 5 are set to 0 to specify that binary encoding is used
158            //
159            // NOTE: the scaling factor is only used to align the implicit point of the mantissa.
160            // This is unnecessary in DER because the base is 2, and therefore necessarily aligned.
161            // Therefore, we do not modify the mantissa in anyway after this function call, which
162            // already adds the implicit one of the IEEE 754 representation.
163            let (_sign, exponent, mantissa) = decode_f64(*self);
164
165            // Encode the exponent as two's complement on 16 bits and remove the bias
166            let exponent_bytes = exponent.to_be_bytes();
167            let ebytes = strip_leading_zeroes(&exponent_bytes);
168
169            match ebytes.len() {
170                0 | 1 => {}
171                2 => first_byte |= 0b0000_0001,
172                3 => first_byte |= 0b0000_0010,
173                _ => {
174                    // TODO: support multi octet exponent encoding?
175                    return Err(Tag::Real.value_error());
176                }
177            }
178
179            writer.write_byte(first_byte)?;
180
181            // Encode both bytes or just the last one, handled by encode_bytes directly
182            // Rust already encodes the data as two's complement, so no further processing is needed
183            writer.write(ebytes)?;
184
185            // Now, encode the mantissa as unsigned binary number
186            let mantissa_bytes = mantissa.to_be_bytes();
187            let mbytes = strip_leading_zeroes(&mantissa_bytes);
188            writer.write(mbytes)?;
189        }
190
191        Ok(())
192    }
193}
194
195impl FixedTag for f64 {
196    const TAG: Tag = Tag::Real;
197}
198
199/// Is the N-th bit 1 in the first octet?
200/// NOTE: this function is zero indexed
201pub(crate) fn is_nth_bit_one<const N: usize>(bytes: &[u8]) -> bool {
202    if N < 8 {
203        bytes
204            .first()
205            .map(|byte| byte & (1 << N) != 0)
206            .unwrap_or(false)
207    } else {
208        false
209    }
210}
211
212/// Convert bits M, N into a u8, in the first octet only
213pub(crate) fn mnth_bits_to_u8<const M: usize, const N: usize>(bytes: &[u8]) -> u8 {
214    let bit_m = is_nth_bit_one::<M>(bytes);
215    let bit_n = is_nth_bit_one::<N>(bytes);
216    (bit_m as u8) << 1 | bit_n as u8
217}
218
219/// Decode an f64 as its sign, exponent, and mantissa in u64 and in that order, using bit shifts and masks.
220/// Note: this function **removes** the 1023 bias from the exponent and adds the implicit 1
221#[allow(clippy::cast_possible_truncation)]
222pub(crate) fn decode_f64(f: f64) -> (u64, u64, u64) {
223    let bits = f.to_bits();
224    let sign = bits >> 63;
225    let exponent = bits >> 52 & 0x7ff;
226    let exponent_bytes_no_bias = (exponent as i16 - 1023).to_be_bytes();
227    let exponent_no_bias = u64::from_be_bytes([
228        0x0,
229        0x0,
230        0x0,
231        0x0,
232        0x0,
233        0x0,
234        exponent_bytes_no_bias[0],
235        exponent_bytes_no_bias[1],
236    ]);
237    let mantissa = bits & 0xfffffffffffff;
238    (sign, exponent_no_bias, mantissa + 1)
239}
240
241/// Encode an f64 from its sign, exponent (**without** the 1023 bias), and (mantissa - 1) using bit shifts as received by ASN1
242pub(crate) fn encode_f64(sign: u64, exponent: u64, mantissa: u64) -> f64 {
243    // Add the bias to the exponent
244    let exponent_with_bias =
245        (i16::from_be_bytes([exponent.to_be_bytes()[6], exponent.to_be_bytes()[7]]) + 1023) as u64;
246    let bits = sign << 63 | exponent_with_bias << 52 | (mantissa - 1);
247    f64::from_bits(bits)
248}
249
250#[cfg(test)]
251mod tests {
252    use crate::{Decode, Encode};
253
254    #[test]
255    fn decode_subnormal() {
256        assert!(f64::from_der(&[0x09, 0x01, 0b0100_0010]).unwrap().is_nan());
257        let plus_infty = f64::from_der(&[0x09, 0x01, 0b0100_0000]).unwrap();
258        assert!(plus_infty.is_infinite() && plus_infty.is_sign_positive());
259        let neg_infty = f64::from_der(&[0x09, 0x01, 0b0100_0001]).unwrap();
260        assert!(neg_infty.is_infinite() && neg_infty.is_sign_negative());
261        let neg_zero = f64::from_der(&[0x09, 0x01, 0b0100_0011]).unwrap();
262        assert!(neg_zero.is_sign_negative() && neg_zero.abs() < f64::EPSILON);
263    }
264
265    #[test]
266    fn encode_subnormal() {
267        // All subnormal fit in three bytes
268        let mut buffer = [0u8; 3];
269        assert_eq!(
270            &[0x09, 0x01, 0b0100_0010],
271            f64::NAN.encode_to_slice(&mut buffer).unwrap()
272        );
273        assert_eq!(
274            &[0x09, 0x01, 0b0100_0000],
275            f64::INFINITY.encode_to_slice(&mut buffer).unwrap()
276        );
277        assert_eq!(
278            &[0x09, 0x01, 0b0100_0001],
279            f64::NEG_INFINITY.encode_to_slice(&mut buffer).unwrap()
280        );
281        assert_eq!(
282            &[0x09, 0x01, 0b0100_0011],
283            (-0.0_f64).encode_to_slice(&mut buffer).unwrap()
284        );
285    }
286
287    #[test]
288    fn encdec_normal() {
289        // The comments correspond to the decoded value from the ASN.1 playground when the bytes are inputed.
290        {
291            // rec1value R ::= 0
292            let val = 0.0;
293            let expected = &[0x09, 0x0];
294            let mut buffer = [0u8; 2];
295            let encoded = val.encode_to_slice(&mut buffer).unwrap();
296            assert_eq!(
297                expected, encoded,
298                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
299                val, encoded, expected
300            );
301            let decoded = f64::from_der(encoded).unwrap();
302            assert!(
303                (decoded - val).abs() < f64::EPSILON,
304                "wanted: {}\tgot: {}",
305                val,
306                decoded
307            );
308        }
309
310        {
311            // rec1value R ::= { mantissa 1, base 2, exponent 0 }
312            let val = 1.0;
313            let expected = &[0x09, 0x03, 0x80, 0x00, 0x01];
314            let mut buffer = [0u8; 5];
315            let encoded = val.encode_to_slice(&mut buffer).unwrap();
316            assert_eq!(
317                expected, encoded,
318                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
319                val, encoded, expected
320            );
321            let decoded = f64::from_der(encoded).unwrap();
322            assert!(
323                (decoded - val).abs() < f64::EPSILON,
324                "wanted: {}\tgot: {}",
325                val,
326                decoded
327            );
328        }
329
330        {
331            // rec1value R ::= { mantissa -1, base 2, exponent 0 }
332            let val = -1.0;
333            let expected = &[0x09, 0x03, 0xc0, 0x00, 0x01];
334            let mut buffer = [0u8; 5];
335            let encoded = val.encode_to_slice(&mut buffer).unwrap();
336            assert_eq!(
337                expected, encoded,
338                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
339                val, encoded, expected
340            );
341            let decoded = f64::from_der(encoded).unwrap();
342            assert!(
343                (decoded - val).abs() < f64::EPSILON,
344                "wanted: {}\tgot: {}",
345                val,
346                decoded
347            );
348        }
349
350        {
351            // rec1value R ::= { mantissa -1, base 2, exponent 1 }
352            let val = -1.0000000000000002;
353            let expected = &[0x09, 0x03, 0xc0, 0x00, 0x02];
354            let mut buffer = [0u8; 5];
355            let encoded = val.encode_to_slice(&mut buffer).unwrap();
356            assert_eq!(
357                expected, encoded,
358                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
359                val, encoded, expected
360            );
361            let decoded = f64::from_der(encoded).unwrap();
362            assert!(
363                (decoded - val).abs() < f64::EPSILON,
364                "wanted: {}\tgot: {}",
365                val,
366                decoded
367            );
368        }
369
370        {
371            // rec1value R ::= { mantissa 1, base 2, exponent -1022 }
372            // NOTE: f64::MIN_EXP == -1021 so the exponent decoded by ASN.1 is what we expect
373            let val = f64::MIN_POSITIVE;
374            let expected = &[0x09, 0x04, 0x81, 0xfc, 0x02, 0x01];
375            let mut buffer = [0u8; 7];
376            let encoded = val.encode_to_slice(&mut buffer).unwrap();
377            assert_eq!(
378                expected, encoded,
379                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
380                val, encoded, expected
381            );
382            let decoded = f64::from_der(encoded).unwrap();
383            assert!(
384                (decoded - val).abs() < f64::EPSILON,
385                "wanted: {}\tgot: {}",
386                val,
387                decoded
388            );
389        }
390
391        {
392            // rec4value R ::= { mantissa 1, base 2, exponent 3 }
393            let val = 1.0000000000000016;
394            let expected = &[0x09, 0x03, 0x80, 0x00, 0x08];
395            let mut buffer = [0u8; 5];
396            let encoded = val.encode_to_slice(&mut buffer).unwrap();
397            assert_eq!(
398                expected, encoded,
399                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
400                val, encoded, expected
401            );
402            let decoded = f64::from_der(encoded).unwrap();
403            assert!(
404                (decoded - val).abs() < f64::EPSILON,
405                "wanted: {}\tgot: {}",
406                val,
407                decoded
408            );
409        }
410
411        {
412            // rec5value R ::= { mantissa 4222124650659841, base 2, exponent 4 }
413            let val = 31.0;
414            let expected = &[
415                0x9, 0x9, 0x80, 0x04, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
416            ];
417            let mut buffer = [0u8; 11];
418            let encoded = val.encode_to_slice(&mut buffer).unwrap();
419            assert_eq!(
420                expected, encoded,
421                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
422                val, encoded, expected
423            );
424            let decoded = f64::from_der(encoded).unwrap();
425            assert!(
426                (decoded - val).abs() < f64::EPSILON,
427                "wanted: {}\tgot: {}",
428                val,
429                decoded
430            );
431        }
432    }
433
434    #[test]
435    fn encdec_irrationals() {
436        {
437            let val = core::f64::consts::PI;
438            let expected = &[
439                0x09, 0x09, 0x80, 0x01, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x19,
440            ];
441            let mut buffer = [0u8; 11];
442            let encoded = val.encode_to_slice(&mut buffer).unwrap();
443            assert_eq!(
444                expected, encoded,
445                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
446                val, encoded, expected
447            );
448            let decoded = f64::from_der(encoded).unwrap();
449            assert!(
450                (decoded - val).abs() < f64::EPSILON,
451                "wanted: {}\tgot: {}",
452                val,
453                decoded
454            );
455        }
456
457        {
458            let val = core::f64::consts::E;
459            let expected = &[
460                0x09, 0x09, 0x80, 0x01, 0x05, 0xbf, 0x0a, 0x8b, 0x14, 0x57, 0x6a,
461            ];
462            let mut buffer = [0u8; 12];
463            let encoded = val.encode_to_slice(&mut buffer).unwrap();
464            assert_eq!(
465                expected, encoded,
466                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
467                val, encoded, expected
468            );
469            let decoded = f64::from_der(encoded).unwrap();
470            assert!(
471                (decoded - val).abs() < f64::EPSILON,
472                "wanted: {}\tgot: {}",
473                val,
474                decoded
475            );
476        }
477        {
478            let val = core::f64::consts::LN_2;
479            let expected = &[
480                0x09, 0x0a, 0x81, 0xff, 0xff, 0x6, 0x2e, 0x42, 0xfe, 0xfa, 0x39, 0xf0,
481            ];
482            let mut buffer = [0u8; 12];
483            let encoded = val.encode_to_slice(&mut buffer).unwrap();
484            assert_eq!(
485                expected, encoded,
486                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
487                val, encoded, expected
488            );
489            let decoded = f64::from_der(encoded).unwrap();
490            assert!(
491                (decoded - val).abs() < f64::EPSILON,
492                "wanted: {}\tgot: {}",
493                val,
494                decoded
495            );
496        }
497    }
498
499    #[test]
500    fn encdec_reasonable_f64() {
501        // Tests the encoding and decoding of reals with some arbitrary numbers
502        {
503            // rec1value R ::= { mantissa 2414341043715239, base 2, exponent 21 }
504            let val = 3221417.1584163485;
505            let expected = &[
506                0x9, 0x9, 0x80, 0x15, 0x8, 0x93, 0xd4, 0x94, 0x46, 0xfc, 0xa7,
507            ];
508            let mut buffer = [0u8; 11];
509            let encoded = val.encode_to_slice(&mut buffer).unwrap();
510            assert_eq!(
511                expected, encoded,
512                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
513                val, encoded, expected
514            );
515            let decoded = f64::from_der(encoded).unwrap();
516            assert!(
517                (decoded - val).abs() < f64::EPSILON,
518                "wanted: {}\tgot: {}",
519                val,
520                decoded
521            );
522        }
523
524        {
525            // rec1value R ::= { mantissa 2671155248072715, base 2, exponent 23 }
526            let val = 13364022.365665454;
527            let expected = &[
528                0x09, 0x09, 0x80, 0x17, 0x09, 0x7d, 0x66, 0xcb, 0xb3, 0x88, 0x0b,
529            ];
530            let mut buffer = [0u8; 12];
531            let encoded = val.encode_to_slice(&mut buffer).unwrap();
532            assert_eq!(
533                expected, encoded,
534                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
535                val, encoded, expected
536            );
537            let decoded = f64::from_der(encoded).unwrap();
538            assert!(
539                (decoded - val).abs() < f64::EPSILON,
540                "wanted: {}\tgot: {}",
541                val,
542                decoded
543            );
544        }
545
546        {
547            // rec1value R ::= { mantissa -4386812962460287, base 2, exponent 14 }
548            let val = -32343.132588105735;
549            let expected = &[
550                0x09, 0x09, 0xc0, 0x0e, 0x0f, 0x95, 0xc8, 0x7c, 0x52, 0xd2, 0x7f,
551            ];
552            let mut buffer = [0u8; 12];
553            let encoded = val.encode_to_slice(&mut buffer).unwrap();
554            assert_eq!(
555                expected, encoded,
556                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
557                val, encoded, expected
558            );
559            let decoded = f64::from_der(encoded).unwrap();
560            assert!(
561                (decoded - val).abs() < f64::EPSILON,
562                "wanted: {}\tgot: {}",
563                val,
564                decoded
565            );
566        }
567
568        {
569            let val = -27084.866751869475;
570            let expected = &[
571                0x09, 0x09, 0xc0, 0x0e, 0x0a, 0x73, 0x37, 0x78, 0xdc, 0xd5, 0x4a,
572            ];
573            let mut buffer = [0u8; 12];
574            let encoded = val.encode_to_slice(&mut buffer).unwrap();
575            assert_eq!(
576                expected, encoded,
577                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
578                val, encoded, expected
579            );
580            let decoded = f64::from_der(encoded).unwrap();
581            assert!(
582                (decoded - val).abs() < f64::EPSILON,
583                "wanted: {}\tgot: {}",
584                val,
585                decoded
586            );
587        }
588
589        {
590            // rec1value R ::= { mantissa -4372913134428149, base 2, exponent 7 }
591            let val = -252.28566647111404;
592            let expected = &[
593                0x09, 0x09, 0xc0, 0x07, 0x0f, 0x89, 0x24, 0x2e, 0x02, 0xdf, 0xf5,
594            ];
595            let mut buffer = [0u8; 12];
596            let encoded = val.encode_to_slice(&mut buffer).unwrap();
597            assert_eq!(
598                expected, encoded,
599                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
600                val, encoded, expected
601            );
602            let decoded = f64::from_der(encoded).unwrap();
603            assert!(
604                (decoded - val).abs() < f64::EPSILON,
605                "wanted: {}\tgot: {}",
606                val,
607                decoded
608            );
609        }
610
611        {
612            let val = -14.399709612928548;
613            let expected = &[
614                0x09, 0x09, 0xc0, 0x03, 0x0c, 0xcc, 0xa6, 0xbd, 0x06, 0xd9, 0x92,
615            ];
616            let mut buffer = [0u8; 12];
617            let encoded = val.encode_to_slice(&mut buffer).unwrap();
618            assert_eq!(
619                expected, encoded,
620                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
621                val, encoded, expected
622            );
623            let decoded = f64::from_der(encoded).unwrap();
624            assert!(
625                (decoded - val).abs() < f64::EPSILON,
626                "wanted: {}\tgot: {}",
627                val,
628                decoded
629            );
630        }
631
632        {
633            let val = -0.08340570261832964;
634            let expected = &[
635                0x09, 0x0a, 0xc1, 0xff, 0xfc, 0x05, 0x5a, 0x13, 0x7d, 0x0b, 0xae, 0x3d,
636            ];
637            let mut buffer = [0u8; 12];
638            let encoded = val.encode_to_slice(&mut buffer).unwrap();
639            assert_eq!(
640                expected, encoded,
641                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
642                val, encoded, expected
643            );
644            let decoded = f64::from_der(encoded).unwrap();
645            assert!(
646                (decoded - val).abs() < f64::EPSILON,
647                "wanted: {}\tgot: {}",
648                val,
649                decoded
650            );
651        }
652
653        {
654            let val = 0.00536851453803701;
655            let expected = &[
656                0x09, 0x0a, 0x81, 0xff, 0xf8, 0x05, 0xfd, 0x4b, 0xa5, 0xe7, 0x4c, 0x93,
657            ];
658            let mut buffer = [0u8; 12];
659            let encoded = val.encode_to_slice(&mut buffer).unwrap();
660            assert_eq!(
661                expected, encoded,
662                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
663                val, encoded, expected
664            );
665            let decoded = f64::from_der(encoded).unwrap();
666            assert!(
667                (decoded - val).abs() < f64::EPSILON,
668                "wanted: {}\tgot: {}",
669                val,
670                decoded
671            );
672        }
673
674        {
675            let val = 0.00045183525648866433;
676            let expected = &[
677                0x09, 0x0a, 0x81, 0xff, 0xf4, 0x0d, 0x9c, 0x89, 0xa6, 0x59, 0x33, 0x39,
678            ];
679            let mut buffer = [0u8; 12];
680            let encoded = val.encode_to_slice(&mut buffer).unwrap();
681            assert_eq!(
682                expected, encoded,
683                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
684                val, encoded, expected
685            );
686            let decoded = f64::from_der(encoded).unwrap();
687            assert!(
688                (decoded - val).abs() < f64::EPSILON,
689                "wanted: {}\tgot: {}",
690                val,
691                decoded
692            );
693        }
694
695        {
696            let val = 0.000033869092002682955;
697            let expected = &[
698                0x09, 0x0a, 0x81, 0xff, 0xf1, 0x01, 0xc1, 0xd5, 0x23, 0xd5, 0x54, 0x7c,
699            ];
700            let mut buffer = [0u8; 12];
701            let encoded = val.encode_to_slice(&mut buffer).unwrap();
702            assert_eq!(
703                expected, encoded,
704                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
705                val, encoded, expected
706            );
707            let decoded = f64::from_der(encoded).unwrap();
708            assert!(
709                (decoded - val).abs() < f64::EPSILON,
710                "wanted: {}\tgot: {}",
711                val,
712                decoded
713            );
714        }
715
716        {
717            let val = 0.0000011770891033600088;
718            let expected = &[
719                0x09, 0x0a, 0x81, 0xff, 0xec, 0x03, 0xbf, 0x8f, 0x27, 0xf4, 0x62, 0x56,
720            ];
721            let mut buffer = [0u8; 12];
722            let encoded = val.encode_to_slice(&mut buffer).unwrap();
723            assert_eq!(
724                expected, encoded,
725                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
726                val, encoded, expected
727            );
728            let decoded = f64::from_der(encoded).unwrap();
729            assert!(
730                (decoded - val).abs() < f64::EPSILON,
731                "wanted: {}\tgot: {}",
732                val,
733                decoded
734            );
735        }
736
737        {
738            let val = 0.00000005549514041997082;
739            let expected = &[
740                0x09, 0x0a, 0x81, 0xff, 0xe7, 0x0d, 0xcb, 0x31, 0xab, 0x6e, 0xb8, 0xd7,
741            ];
742            let mut buffer = [0u8; 12];
743            let encoded = val.encode_to_slice(&mut buffer).unwrap();
744            assert_eq!(
745                expected, encoded,
746                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
747                val, encoded, expected
748            );
749            let decoded = f64::from_der(encoded).unwrap();
750            assert!(
751                (decoded - val).abs() < f64::EPSILON,
752                "wanted: {}\tgot: {}",
753                val,
754                decoded
755            );
756        }
757
758        {
759            let val = 0.0000000012707044685547803;
760            let expected = &[
761                0x09, 0x0a, 0x81, 0xff, 0xe2, 0x05, 0xd4, 0x9e, 0x0a, 0xf2, 0xff, 0x1f,
762            ];
763            let mut buffer = [0u8; 12];
764            let encoded = val.encode_to_slice(&mut buffer).unwrap();
765            assert_eq!(
766                expected, encoded,
767                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
768                val, encoded, expected
769            );
770            let decoded = f64::from_der(encoded).unwrap();
771            assert!(
772                (decoded - val).abs() < f64::EPSILON,
773                "wanted: {}\tgot: {}",
774                val,
775                decoded
776            );
777        }
778
779        {
780            let val = 0.00000000002969611878378562;
781            let expected = &[
782                0x09, 0x09, 0x81, 0xff, 0xdd, 0x53, 0x5b, 0x6f, 0x97, 0xee, 0xb6,
783            ];
784            let mut buffer = [0u8; 11];
785            let encoded = val.encode_to_slice(&mut buffer).unwrap();
786            assert_eq!(
787                expected, encoded,
788                "invalid encoding of {}:\ngot  {:x?}\nwant: {:x?}",
789                val, encoded, expected
790            );
791            let decoded = f64::from_der(encoded).unwrap();
792            assert!(
793                (decoded - val).abs() < f64::EPSILON,
794                "wanted: {}\tgot: {}",
795                val,
796                decoded
797            );
798        }
799    }
800
801    #[test]
802    fn reject_non_canonical() {
803        assert!(f64::from_der(&[0x09, 0x81, 0x00]).is_err());
804    }
805
806    #[test]
807    fn encdec_f64() {
808        use super::{decode_f64, encode_f64};
809        // Test that the extraction and recreation works
810        for val in [
811            1.0,
812            0.1,
813            -0.1,
814            -1.0,
815            0.0,
816            f64::MIN_POSITIVE,
817            f64::MAX,
818            f64::MIN,
819            3.1415,
820            951.2357864,
821            -3.1415,
822            -951.2357864,
823        ] {
824            let (s, e, m) = decode_f64(val);
825            let val2 = encode_f64(s, e, m);
826            assert!(
827                (val - val2).abs() < f64::EPSILON,
828                "fail - want {}\tgot {}",
829                val,
830                val2
831            );
832        }
833    }
834
835    #[test]
836    fn validation_cases() {
837        // Caveat: these test cases are validated on the ASN.1 playground: https://asn1.io/asn1playground/ .
838        // The test case consists in inputing the bytes in the "decode" field and checking that the decoded
839        // value corresponds to the one encoded here.
840        // This tool encodes _all_ values that are non-zero in the ISO 6093 NR3 representation.
841        // This does not seem to perfectly adhere to the ITU specifications, Special Cases section.
842        // The implementation of this crate correctly supports decoding such values. It will, however,
843        // systematically encode REALs in their base 2 form, with a scaling factor where needed to
844        // ensure that the mantissa is either odd or zero (as per section 11.3.1).
845
846        // Positive trivial numbers
847        {
848            let expect = 10.0;
849            let testcase = &[0x09, 0x05, 0x03, 0x31, 0x2E, 0x45, 0x31];
850            let decoded = f64::from_der(testcase).unwrap();
851            assert!(
852                (decoded - expect).abs() < f64::EPSILON,
853                "wanted: {}\tgot: {}",
854                expect,
855                decoded
856            );
857        }
858        {
859            let expect = 100.0;
860            let testcase = &[0x09, 0x05, 0x03, 0x31, 0x2E, 0x45, 0x32];
861            let decoded = f64::from_der(testcase).unwrap();
862            assert!(
863                (decoded - expect).abs() < f64::EPSILON,
864                "wanted: {}\tgot: {}",
865                expect,
866                decoded
867            );
868        }
869        {
870            let expect = 101.0;
871            let testcase = &[0x09, 0x08, 0x03, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30];
872            let decoded = f64::from_der(testcase).unwrap();
873            assert!(
874                (decoded - expect).abs() < f64::EPSILON,
875                "wanted: {}\tgot: {}",
876                expect,
877                decoded
878            );
879        }
880        {
881            let expect = 101.0;
882            let testcase = &[0x09, 0x08, 0x03, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30];
883            let decoded = f64::from_der(testcase).unwrap();
884            assert!(
885                (decoded - expect).abs() < f64::EPSILON,
886                "wanted: {}\tgot: {}",
887                expect,
888                decoded
889            );
890        }
891        {
892            let expect = 0.0;
893            let testcase = &[0x09, 0x00];
894            let decoded = f64::from_der(testcase).unwrap();
895            assert!(
896                (decoded - expect).abs() < f64::EPSILON,
897                "wanted: {}\tgot: {}",
898                expect,
899                decoded
900            );
901        }
902        {
903            let expect = 951.2357864;
904            let testcase = &[
905                0x09, 0x0F, 0x03, 0x39, 0x35, 0x31, 0x32, 0x33, 0x35, 0x37, 0x38, 0x36, 0x34, 0x2E,
906                0x45, 0x2D, 0x37,
907            ];
908            let decoded = f64::from_der(testcase).unwrap();
909            assert!(
910                (decoded - expect).abs() < f64::EPSILON,
911                "wanted: {}\tgot: {}",
912                expect,
913                decoded
914            );
915        }
916        // Negative trivial numbers
917        {
918            let expect = -10.0;
919            let testcase = &[0x09, 0x06, 0x03, 0x2D, 0x31, 0x2E, 0x45, 0x31];
920            let decoded = f64::from_der(testcase).unwrap();
921            assert!(
922                (decoded - expect).abs() < f64::EPSILON,
923                "wanted: {}\tgot: {}",
924                expect,
925                decoded
926            );
927        }
928        {
929            let expect = -100.0;
930            let testcase = &[0x09, 0x06, 0x03, 0x2D, 0x31, 0x2E, 0x45, 0x32];
931            let decoded = f64::from_der(testcase).unwrap();
932            assert!(
933                (decoded - expect).abs() < f64::EPSILON,
934                "wanted: {}\tgot: {}",
935                expect,
936                decoded
937            );
938        }
939        {
940            let expect = -101.0;
941            let testcase = &[
942                0x09, 0x09, 0x03, 0x2D, 0x31, 0x30, 0x31, 0x2E, 0x45, 0x2B, 0x30,
943            ];
944            let decoded = f64::from_der(testcase).unwrap();
945            assert!(
946                (decoded - expect).abs() < f64::EPSILON,
947                "wanted: {}\tgot: {}",
948                expect,
949                decoded
950            );
951        }
952        {
953            let expect = -0.5;
954            let testcase = &[0x09, 0x07, 0x03, 0x2D, 0x35, 0x2E, 0x45, 0x2D, 0x31];
955            let decoded = f64::from_der(testcase).unwrap();
956            assert!(
957                (decoded - expect).abs() < f64::EPSILON,
958                "wanted: {}\tgot: {}",
959                expect,
960                decoded
961            );
962        }
963        {
964            let expect = -0.0;
965            let testcase = &[0x09, 0x03, 0x01, 0x2D, 0x30];
966            let decoded = f64::from_der(testcase).unwrap();
967            assert!(
968                (decoded - expect).abs() < f64::EPSILON,
969                "wanted: {}\tgot: {}",
970                expect,
971                decoded
972            );
973        }
974        {
975            // Test NR3 decoding
976            let expect = -951.2357864;
977            let testcase = &[
978                0x09, 0x10, 0x03, 0x2D, 0x39, 0x35, 0x31, 0x32, 0x33, 0x35, 0x37, 0x38, 0x36, 0x34,
979                0x2E, 0x45, 0x2D, 0x37,
980            ];
981            let decoded = f64::from_der(testcase).unwrap();
982            assert!(
983                (decoded - expect).abs() < f64::EPSILON,
984                "wanted: {}\tgot: {}",
985                expect,
986                decoded
987            );
988        }
989    }
990}