use crate::encoding::read::{Error, Read};
use crate::encoding::write::Write;
use std::cmp::PartialEq;
use std::collections::HashMap;
use std::convert::TryFrom;
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(f64),
BigInt(i64),
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(decoder.read_var::<i64>()? as f64),
124 => Any::Number(decoder.read_f32()? as f64),
123 => Any::Number(decoder.read_f64()?),
122 => Any::BigInt(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::with_capacity(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::with_capacity(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) => {
let num_truncated = num.trunc();
if num_truncated == *num
&& num_truncated <= F64_MAX_SAFE_INTEGER
&& num_truncated >= F64_MIN_SAFE_INTEGER
{
encoder.write_u8(125);
encoder.write_var(num_truncated as i64)
} else if ((*num as f32) as f64) == *num {
encoder.write_u8(124);
encoder.write_f32(*num as f32)
} else {
encoder.write_u8(123);
encoder.write_f64(*num)
}
}
Any::BigInt(num) => {
encoder.write_u8(122);
encoder.write_i64(*num)
}
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::BigInt(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(())
}
}
}
}
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_num {
($t:ty) => {
impl From<$t> for Any {
#[inline]
fn from(v: $t) -> Self {
Self::Number(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) => Ok(num as Self),
Any::BigInt(num) => Ok(num as Self),
other => Err(other),
}
}
}
};
}
macro_rules! impl_from_bigint {
($t:ty) => {
impl From<$t> for Any {
fn from(value: $t) -> Self {
let v = value as f64;
if v <= F64_MAX_SAFE_INTEGER && v >= F64_MIN_SAFE_INTEGER {
Self::Number(v)
} else {
Self::BigInt(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) => Ok(num as Self),
Any::BigInt(num) => Ok(num as Self),
other => Err(other),
}
}
}
};
}
impl_from_num!(f32);
impl_from_num!(f64);
impl_from_num!(i16);
impl_from_num!(i32);
impl_from_num!(u16);
impl_from_num!(u32);
impl_from_bigint!(i64);
impl_from_bigint!(isize);
impl TryFrom<u64> for Any {
type Error = u64;
fn try_from(value: u64) -> Result<Self, Self::Error> {
if value > i64::MAX.abs() as u64 {
Err(value)
} else {
let v = value as f64;
if v <= F64_MAX_SAFE_INTEGER && v >= F64_MIN_SAFE_INTEGER {
Ok(Any::Number(v))
} else {
Ok(Any::BigInt(v as i64))
}
}
}
}
impl TryFrom<Any> for u64 {
type Error = Any;
fn try_from(v: Any) -> Result<Self, Self::Error> {
match v {
Any::Number(num) => Ok(num as Self),
Any::BigInt(num) => Ok(num as Self),
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(value as f64))
}
#[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) => Ok(num as Self),
Any::BigInt(num) => Ok(num as Self),
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)*) => {};
}