1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
use crate::profile::{validate_f64_bits, CANONICAL_NAN_BITS, NEGATIVE_ZERO_BITS};
use crate::{CborError, ErrorCode};
/// A validated float64 bit-pattern suitable for SACP-CBOR/1 encoding.
///
/// - Encoded as CBOR float64 (major 7, ai 27).
/// - `-0.0` is forbidden.
/// - NaN must use the canonical bit pattern `0x7ff8_0000_0000_0000`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct F64Bits(u64);
impl F64Bits {
/// Construct from raw IEEE-754 bits.
///
/// # Errors
///
/// Returns an error if bits encode `-0.0` or a non-canonical NaN.
pub fn new(bits: u64) -> Result<Self, CborError> {
validate_f64_bits(bits).map_err(|code| CborError::new(code, 0))?;
Ok(Self(bits))
}
/// Construct from an `f64` value.
///
/// # Errors
///
/// Returns an error if `value` is `-0.0`. NaNs are canonicalized to the required NaN bit pattern.
pub fn try_from_f64(value: f64) -> Result<Self, CborError> {
let bits = value.to_bits();
if bits == NEGATIVE_ZERO_BITS {
return Err(CborError::new(ErrorCode::NegativeZeroForbidden, 0));
}
if value.is_nan() {
return Ok(Self(CANONICAL_NAN_BITS));
}
Ok(Self(bits))
}
/// Return the raw IEEE-754 bits.
#[inline]
#[must_use]
pub const fn bits(self) -> u64 {
self.0
}
/// Convert into an `f64`.
#[inline]
#[must_use]
pub fn to_f64(self) -> f64 {
f64::from_bits(self.0)
}
}