graphql_query/ast/
ast_util.rs1use super::ast::FloatValue;
7use core::hash::{Hash, Hasher};
8
9const SIGN_MASK: u64 = 0x8000_0000_0000_0000_u64;
11const EXP_MASK: u64 = 0x7ff0_0000_0000_0000_u64;
12const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff_u64;
13
14const CANONICAL_NAN_BITS: u64 = 0x7ff8_0000_0000_0000_u64;
16const CANONICAL_ZERO_BITS: u64 = 0x0u64;
17
18#[inline]
19fn raw_double_bits(f: &f64) -> u64 {
20 if f.is_nan() {
21 return CANONICAL_NAN_BITS;
22 }
23
24 let bits: u64 = f.to_bits();
26 let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
27 let mut exp: i16 = ((bits >> 52) & 0x7ff) as i16;
28 let man = if exp == 0 {
29 (bits & 0x000f_ffff_ffff_ffff) << 1
30 } else {
31 (bits & 0x000f_ffff_ffff_ffff) | 0x0010_0000_0000_0000
32 };
33 exp -= 1023 + 52;
35
36 if man == 0 {
37 return CANONICAL_ZERO_BITS;
38 }
39
40 let man_u64 = man;
41 let exp_u64 = u64::from(exp as u16);
42 let sign_u64 = if sign > 0 { 1u64 } else { 0u64 };
43 (man_u64 & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK)
44}
45
46impl<'a> Hash for FloatValue<'a> {
47 fn hash<H: Hasher>(&self, state: &mut H) {
48 let float = self.value.parse::<f64>().unwrap_or(0.0);
49 if float.is_nan() {
50 raw_double_bits(&f64::NAN).hash(state);
51 } else {
52 raw_double_bits(&float).hash(state);
53 }
54 }
55}
56
57impl<'a> PartialEq for FloatValue<'a> {
58 fn eq(&self, other: &Self) -> bool {
59 self.value == other.value
60 }
61}
62
63impl<'a> Eq for FloatValue<'a> {}