use crate::encoding::read::{Error, Read};
use crate::encoding::write::Write;
use serde::de::Visitor;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::fmt::Formatter;
use std::sync::Arc;
pub const F64_MAX_SAFE_INTEGER: f64 = (i64::pow(2, 53) - 1) as f64;
pub const F64_MIN_SAFE_INTEGER: f64 = -F64_MAX_SAFE_INTEGER;
#[derive(Debug, Clone, PartialEq)]
pub enum Any {
Null,
Undefined,
Bool(bool),
Number(Number),
String(Arc<str>),
Buffer(Arc<[u8]>),
Array(Arc<[Any]>),
Map(Arc<HashMap<String, Any>>),
}
impl Any {
#[inline]
pub fn cast<T>(self) -> Result<T, Self>
where
T: TryFrom<Any, Error = Any>,
{
T::try_from(self)
}
pub fn decode<R: Read>(decoder: &mut R) -> Result<Self, Error> {
Ok(match decoder.read_u8()? {
127 => Any::Undefined,
126 => Any::Null,
125 => Any::Number(Number::Int(decoder.read_var::<i64>()?)),
124 => Any::Number(Number::Float(decoder.read_f32()? as f64)),
123 => Any::Number(Number::Float(decoder.read_f64()?)),
122 => Any::Number(Number::Int(decoder.read_i64()?)),
121 => Any::Bool(false),
120 => Any::Bool(true),
119 => {
let str = decoder.read_string()?;
Any::String(Arc::from(str))
}
118 => {
let len: usize = decoder.read_var()?;
let mut map = HashMap::new();
map.try_reserve(len)?;
for _ in 0..len {
let key = decoder.read_string()?;
map.insert(key.to_owned(), Any::decode(decoder)?);
}
Any::Map(Arc::new(map))
}
117 => {
let len: usize = decoder.read_var()?;
let mut arr = Vec::new();
arr.try_reserve(len)?;
for _ in 0..len {
arr.push(Any::decode(decoder)?);
}
Any::Array(Arc::from(arr))
}
116 => Any::Buffer(Arc::from(decoder.read_buf()?)),
_ => return Err(Error::UnexpectedValue),
})
}
pub fn encode<W: Write>(&self, encoder: &mut W) {
match self {
Any::Undefined => {
encoder.write_u8(127)
}
Any::Null => {
encoder.write_u8(126)
}
Any::Bool(bool) => {
encoder.write_u8(if *bool { 120 } else { 121 })
}
Any::String(str) => {
encoder.write_u8(119);
encoder.write_string(&str)
}
Any::Number(num) => {
match *num {
Number::Int(n) => {
if n >= -0x7FFFFFFF && n <= 0x7FFFFFFF {
encoder.write_u8(125);
encoder.write_var(n)
} else if (n as f32) as i64 == n {
encoder.write_u8(124);
encoder.write_f32(n as f32)
} else if (n as f64) as i64 == n {
encoder.write_u8(123);
encoder.write_f64(n as f64)
} else {
encoder.write_u8(122);
encoder.write_i64(n)
}
}
Number::Float(n) => {
if (n as f32) as f64 == n {
encoder.write_u8(124);
encoder.write_f32(n as f32)
} else {
encoder.write_u8(123);
encoder.write_f64(n)
}
}
}
}
Any::Array(arr) => {
encoder.write_u8(117);
encoder.write_var(arr.len() as u64);
for el in arr.iter() {
el.encode(encoder);
}
}
Any::Map(map) => {
encoder.write_u8(118);
encoder.write_var(map.len() as u64);
for (key, value) in map.as_ref() {
encoder.write_string(&key);
value.encode(encoder);
}
}
Any::Buffer(buf) => {
encoder.write_u8(116);
encoder.write_buf(&buf)
}
}
}
pub fn from_json(src: &str) -> Result<Self, Error> {
Ok(serde_json::from_str(src)?)
}
pub fn to_json(&self, buf: &mut String) {
use serde::Serialize;
use serde_json::Serializer;
let buf = unsafe { buf.as_mut_vec() };
let cursor = std::io::Cursor::new(buf);
let mut s = Serializer::new(cursor);
self.serialize(&mut s).unwrap();
}
pub fn try_iter(&self) -> Option<AnyIter<'_>> {
match self {
Any::Array(values) => Some(AnyIter::Array(values.iter())),
Any::Map(entries) => Some(AnyIter::Map(entries.iter())),
_ => None,
}
}
pub fn try_into_iter(self) -> Option<AnyIntoIter> {
match self {
Any::Array(values) => Some(AnyIntoIter::from(values.clone())),
Any::Map(entries) => Some(AnyIntoIter::from(entries.clone())),
_ => None,
}
}
}
impl std::fmt::Display for Any {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Any::Null => f.write_str("null"),
Any::Undefined => f.write_str("undefined"),
Any::Bool(value) => write!(f, "{}", value),
Any::Number(value) => write!(f, "{}", value),
Any::String(value) => f.write_str(value.as_ref()),
Any::Array(values) => {
write!(f, "[")?;
let mut i = values.iter();
if let Some(value) = i.next() {
value.fmt(f)?;
}
while let Some(value) = i.next() {
write!(f, ", ")?;
value.fmt(f)?;
}
write!(f, "]")
}
Any::Map(entries) => {
write!(f, "{{")?;
let mut i = entries.iter();
if let Some((key, value)) = i.next() {
write!(f, "{}: {}", key, value)?;
}
while let Some((key, value)) = i.next() {
write!(f, ", {}: {}", key, value)?;
}
write!(f, "}}")
}
Any::Buffer(value) => {
f.write_str("0x")?;
for &byte in value.iter() {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Number {
Int(i64),
Float(f64),
}
impl Number {
pub const I64_MAX_SAFE_INTEGER: i64 = i64::pow(2, 53) - 1;
pub const I64_MIN_SAFE_INTEGER: i64 = -Self::I64_MAX_SAFE_INTEGER;
pub const F64_MAX_SAFE_INTEGER: f64 = Self::I64_MAX_SAFE_INTEGER as f64;
pub const F64_MIN_SAFE_INTEGER: f64 = -Self::F64_MAX_SAFE_INTEGER;
pub fn try_i64(value: f64) -> Self {
if value.trunc() == value
&& value >= Self::F64_MIN_SAFE_INTEGER
&& value <= Self::F64_MAX_SAFE_INTEGER
{
Number::Int(value as i64)
} else {
Number::Float(value)
}
}
pub fn as_i64(self) -> Option<i64> {
match self {
Number::Int(value) => Some(value),
Number::Float(value) => {
let converted = value as i64;
if converted as f64 == value {
Some(converted)
} else {
None
}
}
}
}
pub fn as_f64(self) -> Option<f64> {
match self {
Number::Int(value) => {
let n = value as f64;
if n as i64 == value {
Some(n)
} else {
None
}
}
Number::Float(value) => Some(value),
}
}
}
impl PartialEq for Number {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Number::Int(a), Number::Int(b)) => a == b,
(Number::Float(a), Number::Float(b)) => a == b,
_ => match (self.as_f64(), other.as_f64()) {
(Some(a), Some(b)) => a == b,
_ => false,
},
}
}
}
impl From<f64> for Number {
#[inline]
fn from(value: f64) -> Self {
Number::Float(value)
}
}
impl From<i64> for Number {
#[inline]
fn from(value: i64) -> Self {
Number::Int(value)
}
}
impl TryFrom<u64> for Number {
type Error = u64;
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value <= i64::MAX as u64 {
Ok(Number::Int(value as i64))
} else {
Err(value)
}
}
}
impl Serialize for Number {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use serde::ser::Error;
match self.as_f64() {
Some(v) => serializer.serialize_f64(v),
None => match self.as_i64() {
Some(v) => serializer.serialize_i64(v),
None => Err(S::Error::custom("cannot serialize number")),
},
}
}
}
impl<'de> Deserialize<'de> for Number {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct NumberVisitor;
impl<'de> Visitor<'de> for NumberVisitor {
type Value = Number;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
write!(formatter, "number")
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if v > (i64::MAX as u64) {
return Err(E::custom("integer outside of bounds of i64"));
}
Ok(Number::Int(v as i64))
}
fn visit_i64<E>(self, value: i64) -> Result<Number, E> {
Ok(Number::Int(value))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if v <= Number::F64_MAX_SAFE_INTEGER
&& v > Number::F64_MIN_SAFE_INTEGER
&& v.trunc() == v
{
Ok(Number::Int(v as i64))
} else {
Ok(Number::Float(v))
}
}
}
deserializer.deserialize_any(NumberVisitor)
}
}
impl std::fmt::Display for Number {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Number::Int(value) => write!(f, "{}", value),
Number::Float(value) => write!(f, "{}", value),
}
}
}
pub enum AnyIter<'a> {
Array(std::slice::Iter<'a, Any>),
Map(std::collections::hash_map::Iter<'a, String, Any>),
}
impl<'a> Iterator for AnyIter<'a> {
type Item = (Option<&'a str>, &'a Any);
fn next(&mut self) -> Option<Self::Item> {
match self {
AnyIter::Array(iter) => {
let value = iter.next()?;
Some((None, value))
}
AnyIter::Map(iter) => {
let (key, value) = iter.next()?;
Some((Some(key), value))
}
}
}
}
pub struct AnyArrayIter {
source: Arc<[Any]>,
index: usize,
}
impl AnyArrayIter {
pub fn new(source: Arc<[Any]>) -> Self {
Self { source, index: 0 }
}
}
impl Iterator for AnyArrayIter {
type Item = Any;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.source.len() {
let value = self.source[self.index].clone();
self.index += 1;
Some(value)
} else {
None
}
}
}
pub enum AnyIntoIter {
Array(AnyArrayIter),
Map(std::collections::hash_map::IntoIter<String, Any>),
}
impl From<Arc<[Any]>> for AnyIntoIter {
fn from(value: Arc<[Any]>) -> Self {
Self::Array(AnyArrayIter::new(value))
}
}
impl From<Arc<HashMap<String, Any>>> for AnyIntoIter {
fn from(value: Arc<HashMap<String, Any>>) -> Self {
Self::Map((&*value).clone().into_iter())
}
}
impl Iterator for AnyIntoIter {
type Item = (Option<String>, Any);
fn next(&mut self) -> Option<Self::Item> {
match self {
AnyIntoIter::Array(iter) => {
let n = iter.next()?;
Some((None, n))
}
AnyIntoIter::Map(iter) => {
let (key, value) = iter.next()?;
Some((Some(key.clone()), value.clone()))
}
}
}
}
macro_rules! impl_from_float {
($t:ty) => {
impl From<$t> for Any {
#[inline]
fn from(v: $t) -> Self {
Self::Number(Number::Float(v as f64))
}
}
impl TryFrom<Any> for $t {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Number(num) => match num.as_f64() {
Some(n) => Ok(n as Self),
None => Err(v),
},
other => Err(other),
}
}
}
};
}
macro_rules! impl_from_int {
($t:ty) => {
impl From<$t> for Any {
fn from(value: $t) -> Self {
Any::Number(Number::from(value as i64))
}
}
impl TryFrom<Any> for $t {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Number(num) => match num.as_i64() {
Some(n) => Ok(n as Self),
None => Err(v),
},
other => Err(other),
}
}
}
};
}
impl_from_float!(f32);
impl_from_float!(f64);
impl_from_int!(i16);
impl_from_int!(i32);
impl_from_int!(u16);
impl_from_int!(u32);
impl_from_int!(i64);
impl_from_int!(isize);
impl TryFrom<u64> for Any {
type Error = u64;
fn try_from(value: u64) -> Result<Self, Self::Error> {
Ok(Any::Number(Number::try_from(value)?))
}
}
impl TryFrom<Any> for u64 {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Number(num) => match num.as_i64() {
Some(n) if n >= 0 => Ok(n as u64),
_ => Err(Any::Number(num)),
},
other => Err(other),
}
}
}
impl TryFrom<usize> for Any {
type Error = usize;
#[cfg(target_pointer_width = "32")]
fn try_from(value: usize) -> Result<Self, Self::Error> {
Ok(Any::Number(Number::Int(value as i64)))
}
#[cfg(target_pointer_width = "64")]
fn try_from(value: usize) -> Result<Self, Self::Error> {
use std::convert::TryInto;
if let Ok(v) = (value as u64).try_into() {
Ok(v)
} else {
Err(value)
}
}
}
impl TryFrom<Any> for usize {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Number(num) => match num.as_i64() {
Some(n) if n >= 0 => Ok(n as usize),
_ => Err(v),
},
other => Err(other),
}
}
}
impl From<bool> for Any {
#[inline]
fn from(value: bool) -> Self {
Any::Bool(value)
}
}
impl TryFrom<Any> for bool {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Bool(num) => Ok(num),
other => Err(other),
}
}
}
impl From<String> for Any {
#[inline]
fn from(value: String) -> Self {
Any::String(value.into())
}
}
impl TryFrom<Any> for String {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::String(value) => Ok(String::from(value.as_ref())),
other => Err(other),
}
}
}
impl From<&str> for Any {
#[inline]
fn from(value: &str) -> Self {
Any::String(value.into())
}
}
impl From<Arc<str>> for Any {
#[inline]
fn from(value: Arc<str>) -> Self {
Any::String(value.clone())
}
}
impl TryFrom<Any> for Arc<str> {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::String(value) => Ok(value),
other => Err(other),
}
}
}
impl From<Vec<u8>> for Any {
#[inline]
fn from(value: Vec<u8>) -> Self {
Any::Buffer(Arc::from(value))
}
}
impl TryFrom<Any> for Vec<u8> {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Buffer(value) => Ok(Vec::from(value.as_ref())),
other => Err(other),
}
}
}
impl From<Arc<[u8]>> for Any {
#[inline]
fn from(value: Arc<[u8]>) -> Self {
Any::Buffer(value)
}
}
impl TryFrom<Any> for Arc<[u8]> {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Buffer(value) => Ok(value),
other => Err(other),
}
}
}
impl From<&[u8]> for Any {
#[inline]
fn from(value: &[u8]) -> Self {
Any::Buffer(Arc::from(value))
}
}
impl<T> From<Option<T>> for Any
where
T: Into<Any>,
{
fn from(v: Option<T>) -> Any {
match v {
None => Any::Null,
Some(value) => value.into(),
}
}
}
impl<T> From<Vec<T>> for Any
where
T: Into<Any>,
{
fn from(v: Vec<T>) -> Any {
let mut array = Vec::with_capacity(v.len());
for value in v {
array.push(value.into())
}
Any::Array(Arc::from(array))
}
}
impl<T> From<HashMap<String, T>> for Any
where
T: Into<Any>,
{
fn from(v: HashMap<String, T>) -> Any {
let mut map = HashMap::with_capacity(v.len());
for (key, value) in v {
map.insert(key, value.into());
}
Any::Map(Arc::new(map))
}
}
#[macro_export(local_inner_macros)]
macro_rules! any {
($($any:tt)+) => {
any_internal!($($any)+)
};
}
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! any_internal {
(@array [$($items:expr,)*]) => {
any_internal_array![$($items,)*]
};
(@array [$($items:expr),*]) => {
any_internal_array![$($items),*]
};
(@array [$($items:expr,)*] null $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!(null)] $($rest)*)
};
(@array [$($items:expr,)*] true $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!(true)] $($rest)*)
};
(@array [$($items:expr,)*] false $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!(false)] $($rest)*)
};
(@array [$($items:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!([$($array)*])] $($rest)*)
};
(@array [$($items:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!({$($map)*})] $($rest)*)
};
(@array [$($items:expr,)*] $next:expr, $($rest:tt)*) => {
any_internal!(@array [$($items,)* any_internal!($next),] $($rest)*)
};
(@array [$($items:expr,)*] $last:expr) => {
any_internal!(@array [$($items,)* any_internal!($last)])
};
(@array [$($items:expr),*] , $($rest:tt)*) => {
any_internal!(@array [$($items,)*] $($rest)*)
};
(@array [$($items:expr),*] $unexpected:tt $($rest:tt)*) => {
any_unexpected!($unexpected)
};
(@object $object:ident () () ()) => {};
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
let _ = $object.insert(($($key)+).into(), $value);
any_internal!(@object $object () ($($rest)*) ($($rest)*));
};
(@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
any_unexpected!($unexpected);
};
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
let _ = $object.insert(($($key)+).into(), $value);
};
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!(null)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!(true)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!(false)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!([$($array)*])) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!({$($map)*})) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!($value)) , $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
any_internal!(@object $object [$($key)+] (any_internal!($value)));
};
(@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
any_internal!();
};
(@object $object:ident ($($key:tt)+) () $copy:tt) => {
any_internal!();
};
(@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
any_unexpected!($colon);
};
(@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
any_unexpected!($comma);
};
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
};
(@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
json_expect_expr_comma!($($unexpected)+);
};
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
any_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
};
(null) => {
$crate::any::Any::Null
};
(true) => {
$crate::any::Any::Bool(true)
};
(false) => {
$crate::any::Any::Bool(false)
};
([]) => {
$crate::any::Any::Array(any_internal_array![])
};
([ $($tt:tt)+ ]) => {
$crate::any::Any::Array(any_internal!(@array [] $($tt)+))
};
({}) => {
$crate::any::Any::Map(std::sync::Arc::new(std::collections::HashMap::new()))
};
({ $($tt:tt)+ }) => {
$crate::any::Any::Map({
let mut object = std::collections::HashMap::new();
any_internal!(@object object () ($($tt)+) ($($tt)+));
std::sync::Arc::new(object)
})
};
($other:expr) => {
($other).into()
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! any_internal_array {
($($content:tt)*) => {
std::sync::Arc::from([$($content)*])
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! any_unexpected {
() => {};
}
#[macro_export]
#[doc(hidden)]
macro_rules! any_expect_expr_comma {
($e:expr , $($tt:tt)*) => {};
}
#[cfg(test)]
mod test {
use crate::any::Any;
use crate::encoding::read::Cursor;
use crate::Number;
#[test]
fn decode_map_rejects_length_amplification() {
let adversarial = [118u8, 0xFF, 0xFF, 0xFF, 0x7A];
let mut cursor = Cursor::new(&adversarial);
assert!(
Any::decode(&mut cursor).is_err(),
"an oversized Any::Map length must be rejected, not eagerly allocated"
);
}
#[test]
fn decode_array_rejects_length_amplification() {
let adversarial = [117u8, 0xFF, 0xFF, 0xFF, 0x7A];
let mut cursor = Cursor::new(&adversarial);
assert!(
Any::decode(&mut cursor).is_err(),
"an oversized Any::Array length must be rejected, not eagerly allocated"
);
}
fn hex(n: Number) -> String {
let mut buf = Vec::new();
Any::Number(n).encode(&mut buf);
buf.iter().map(|b| format!("{:02x}", b)).collect()
}
#[test]
fn number_encoding_yjs_compat() {
assert_eq!(hex(Number::Int(0)), "7d00");
assert_eq!(hex(Number::Int(42)), "7d2a");
assert_eq!(hex(Number::Int(-42)), "7d6a");
assert_eq!(hex(Number::Int(2147483647)), "7dbfffffff0f");
assert_eq!(hex(Number::Int(2147483648)), "7c4f000000");
assert_eq!(hex(Number::Int(-2147483648)), "7ccf000000");
assert_eq!(hex(Number::Int(4294967295)), "7b41efffffffe00000");
assert_eq!(hex(Number::Int(9007199254740991)), "7b433fffffffffffff");
assert_eq!(hex(Number::Float(1.5)), "7c3fc00000");
assert_eq!(hex(Number::Float(1.1)), "7b3ff199999999999a");
assert_eq!(hex(Number::Float(2147483648.0)), "7c4f000000");
assert_eq!(hex(Number::Float(5e9)), "7c4f9502f9");
assert_eq!(hex(Number::Float(1e30)), "7b46293e5939a08cea");
assert_eq!(hex(Number::Float(f64::NAN)), "7b7ff8000000000000");
assert_eq!(hex(Number::Float(f64::INFINITY)), "7c7f800000");
assert_eq!(hex(Number::Float(f64::NEG_INFINITY)), "7cff800000");
}
}