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 
10 use crate::{
11     BytesRef, DecodeValue, EncodeValue, FixedTag, Header, Length, Reader, Result, StrRef, Tag,
12     Writer,
13 };
14 
15 use super::integer::uint::strip_leading_zeroes;
16 
17 impl<'a> DecodeValue<'a> for f64 {
decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self>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 
86 impl EncodeValue for f64 {
value_len(&self) -> Result<Length>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 
encode_value(&self, writer: &mut impl Writer) -> Result<()>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 
195 impl 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
is_nth_bit_one<const N: usize>(bytes: &[u8]) -> bool201 pub(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
mnth_bits_to_u8<const M: usize, const N: usize>(bytes: &[u8]) -> u8213 pub(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)]
decode_f64(f: f64) -> (u64, u64, u64)222 pub(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
encode_f64(sign: u64, exponent: u64, mantissa: u64) -> f64242 pub(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)]
251 mod tests {
252     use crate::{Decode, Encode};
253 
254     #[test]
decode_subnormal()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]
encode_subnormal()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]
encdec_normal()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]
encdec_irrationals()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]
encdec_reasonable_f64()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]
reject_non_canonical()802     fn reject_non_canonical() {
803         assert!(f64::from_der(&[0x09, 0x81, 0x00]).is_err());
804     }
805 
806     #[test]
encdec_f64()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]
validation_cases()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 }
991