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