use crate::value::map::ValueMap;
use std::fmt::{self, Debug, Display};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
pub mod map;
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
Null,
Bool(bool),
I32(i32),
I64(i64),
U32(u32),
U64(u64),
F32(f32),
F64(f64),
String(String),
Binary(Vec<u8>),
Array(Vec<Self>),
Map(ValueMap),
Ext(&'static str, Box<Self>),
}
impl Value {
#[inline]
pub fn is_null(&self) -> bool {
if let Value::Null = *self {
true
} else {
false
}
}
#[inline]
pub fn is_bool(&self) -> bool {
self.as_bool().is_some()
}
#[inline]
pub fn is_i64(&self) -> bool {
if let Value::I64(_) = *self {
true
} else {
false
}
}
#[inline]
pub fn is_i32(&self) -> bool {
if let Value::I32(_) = *self {
true
} else {
false
}
}
#[inline]
pub fn is_u64(&self) -> bool {
if let Value::U64(_) = *self {
true
} else {
false
}
}
#[inline]
pub fn is_f32(&self) -> bool {
if let Value::F32(..) = *self {
true
} else {
false
}
}
#[inline]
pub fn is_f64(&self) -> bool {
if let Value::F64(..) = *self {
true
} else {
false
}
}
pub fn is_number(&self) -> bool {
match *self {
Value::I64(..) | Value::U64(..) | Value::F32(..) | Value::F64(..) => true,
_ => false,
}
}
#[inline]
pub fn is_str(&self) -> bool {
self.as_str().is_some()
}
#[inline]
pub fn is_bin(&self) -> bool {
self.as_slice().is_some()
}
#[inline]
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
#[inline]
pub fn is_map(&self) -> bool {
self.as_map().is_some()
}
#[inline]
pub fn is_ext(&self) -> bool {
self.as_ext().is_some()
}
#[inline]
pub fn as_bool(&self) -> Option<bool> {
match self {
Value::Bool(v) => Some(*v),
Value::Ext(_, e) => e.as_bool(),
_ => None,
}
}
#[inline]
pub fn as_i64(&self) -> Option<i64> {
match *self {
Value::F32(ref n) => Some(n.to_owned() as i64),
Value::F64(ref n) => Some(n.to_owned() as i64),
Value::U64(ref n) => Some(n.to_owned() as i64),
Value::U32(ref n) => Some(n.to_owned() as i64),
Value::I64(ref n) => Some(n.to_owned()),
Value::I32(ref n) => Some(n.to_owned() as i64),
Value::Ext(_, ref e) => e.as_i64(),
_ => None,
}
}
#[inline]
pub fn as_u64(&self) -> Option<u64> {
match *self {
Value::F32(ref n) => Some(n.to_owned() as u64),
Value::F64(ref n) => Some(n.to_owned() as u64),
Value::I64(ref n) => Some(n.to_owned() as u64),
Value::I32(ref n) => Some(n.to_owned() as u64),
Value::U64(ref n) => Some(n.to_owned()),
Value::U32(ref n) => Some(n.to_owned() as u64),
Value::Ext(_, ref e) => e.as_u64(),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match *self {
Value::I32(n) => Some(n as f64),
Value::U32(n) => Some(n as f64),
Value::I64(n) => Some(n as f64),
Value::U64(n) => Some(n as f64),
Value::F32(n) => Some(From::from(n)),
Value::F64(n) => Some(n),
Value::Ext(_, ref e) => e.as_f64(),
_ => None,
}
}
#[inline]
pub fn as_str(&self) -> Option<&str> {
match self {
Value::String(s) => Some(s),
Value::Ext(_, s) => s.as_str(),
_ => None,
}
}
#[inline]
pub fn as_string(&self) -> Option<String> {
match self {
Value::String(v) => Some(v.to_string()),
Value::Ext(_, ext) => ext.as_string(),
_ => None,
}
}
#[inline]
pub fn into_string(self) -> Option<String> {
match self {
Value::String(v) => Some(v),
Value::Ext(_, ext) => ext.into_string(),
_ => None,
}
}
#[inline]
pub fn into_bytes(self) -> Option<Vec<u8>> {
match self {
Value::Binary(v) => Some(v),
Value::Ext(_, ext) => ext.into_bytes(),
Value::Null => Some(vec![]),
Value::Bool(v) => Some(v.to_string().into_bytes()),
Value::I32(v) => Some(v.to_string().into_bytes()),
Value::I64(v) => Some(v.to_string().into_bytes()),
Value::U32(v) => Some(v.to_string().into_bytes()),
Value::U64(v) => Some(v.to_string().into_bytes()),
Value::F32(v) => Some(v.to_string().into_bytes()),
Value::F64(v) => Some(v.to_string().into_bytes()),
Value::String(v) => Some(v.into_bytes()),
Value::Array(_) => Some(self.to_string().into_bytes()),
Value::Map(_) => Some(self.to_string().into_bytes()),
}
}
pub fn as_slice(&self) -> Option<&[u8]> {
if let Value::Binary(ref val) = *self {
Some(val)
} else if let Value::String(ref val) = *self {
Some(val.as_bytes())
} else if let Value::Ext(_, ref val) = *self {
val.as_slice()
} else {
None
}
}
#[inline]
pub fn as_array(&self) -> Option<&Vec<Value>> {
if let Value::Array(ref array) = *self {
Some(&*array)
} else if let Value::Ext(_, ref ext) = *self {
ext.as_array()
} else {
None
}
}
#[inline]
pub fn as_map(&self) -> Option<&ValueMap> {
if let Value::Map(ref map) = *self {
Some(map)
} else if let Value::Ext(_, ref map) = *self {
map.as_map()
} else {
None
}
}
#[inline]
pub fn as_ext(&self) -> Option<(&str, &Box<Value>)> {
if let Value::Ext(ref ty, ref buf) = *self {
Some((ty, buf))
} else {
None
}
}
#[inline]
pub fn into_map(self) -> Option<ValueMap> {
if let Value::Map(map) = self {
Some(map)
} else if let Value::Ext(_, map) = self {
map.into_map()
} else {
None
}
}
#[inline]
pub fn into_array(self) -> Option<Vec<Value>> {
if let Value::Array(array) = self {
Some(array)
} else if let Value::Ext(_, ext) = self {
ext.into_array()
} else {
None
}
}
}
impl From<bool> for Value {
#[inline]
fn from(v: bool) -> Self {
Value::Bool(v)
}
}
impl From<u8> for Value {
#[inline]
fn from(v: u8) -> Self {
Value::U64(From::from(v))
}
}
impl From<u16> for Value {
#[inline]
fn from(v: u16) -> Self {
Value::U64(From::from(v))
}
}
impl From<u32> for Value {
#[inline]
fn from(v: u32) -> Self {
Value::U64(From::from(v))
}
}
impl From<u64> for Value {
#[inline]
fn from(v: u64) -> Self {
Value::U64(From::from(v))
}
}
impl From<usize> for Value {
#[inline]
fn from(v: usize) -> Self {
Value::U64(From::from(v as u64))
}
}
impl From<i8> for Value {
#[inline]
fn from(v: i8) -> Self {
Value::I64(From::from(v))
}
}
impl From<i16> for Value {
#[inline]
fn from(v: i16) -> Self {
Value::I64(From::from(v))
}
}
impl From<i32> for Value {
#[inline]
fn from(v: i32) -> Self {
Value::I64(From::from(v))
}
}
impl From<i64> for Value {
#[inline]
fn from(v: i64) -> Self {
Value::I64(From::from(v))
}
}
impl From<isize> for Value {
#[inline]
fn from(v: isize) -> Self {
Value::I64(From::from(v as i64))
}
}
impl From<f32> for Value {
#[inline]
fn from(v: f32) -> Self {
Value::F32(v)
}
}
impl From<f64> for Value {
#[inline]
fn from(v: f64) -> Self {
Value::F64(v)
}
}
impl From<String> for Value {
#[inline]
fn from(v: String) -> Self {
Value::String(v)
}
}
impl<'a> From<&'a str> for Value {
#[inline]
fn from(v: &str) -> Self {
Value::String(v.to_string())
}
}
impl From<Vec<u8>> for Value {
#[inline]
fn from(v: Vec<u8>) -> Self {
Value::Binary(v)
}
}
impl<'a> From<&'a [u8]> for Value {
#[inline]
fn from(v: &[u8]) -> Self {
Value::Binary(v.into())
}
}
impl From<Vec<Value>> for Value {
#[inline]
fn from(v: Vec<Value>) -> Self {
Value::Array(v)
}
}
impl From<(&'static str, Value)> for Value {
fn from(arg: (&'static str, Value)) -> Self {
Value::Ext(arg.0, Box::new(arg.1))
}
}
impl Into<Vec<Value>> for Value {
fn into(self) -> Vec<Value> {
match self {
Value::Array(arr) => arr,
_ => vec![],
}
}
}
impl Into<ValueMap> for Value {
fn into(self) -> ValueMap {
match self {
Value::Map(arr) => arr,
_ => ValueMap::new(),
}
}
}
impl<V> FromIterator<V> for Value
where
V: Into<Value>,
{
fn from_iter<I: IntoIterator<Item=V>>(iter: I) -> Self {
let v: Vec<Value> = iter.into_iter().map(|v| v.into()).collect();
Value::Array(v)
}
}
impl Display for Value {
#[cold]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match self {
Value::Null => f.write_str("null"),
Value::Bool(val) => Display::fmt(&val, f),
Value::I32(ref val) => Display::fmt(&val, f),
Value::I64(ref val) => Display::fmt(&val, f),
Value::U32(ref val) => Display::fmt(&val, f),
Value::U64(ref val) => Display::fmt(&val, f),
Value::F32(val) => Display::fmt(&val, f),
Value::F64(val) => Display::fmt(&val, f),
Value::String(val) => {
f.write_str("\"")?;
Display::fmt(val, f)?;
f.write_str("\"")
}
Value::Binary(ref val) => {
if val.len() > 32 {
Debug::fmt(&val[0..32], f)
} else {
Debug::fmt(val, f)
}
},
Value::Array(ref vec) => {
f.write_str("[")?;
let mut i = 0;
for x in vec {
Display::fmt(&x, f)?;
i += 1;
if i != vec.len() {
f.write_str(",")?;
}
}
f.write_str("]")?;
Ok(())
}
Value::Map(ref vec) => Display::fmt(vec, f),
Value::Ext(_, ref data) => {
write!(f, "{}", data.deref())
}
}
}
}
impl Default for Value {
fn default() -> Self {
Value::Null
}
}
impl IntoIterator for Value {
type Item = (Value, Value);
type IntoIter = indexmap::map::IntoIter<Value, Value>;
fn into_iter(self) -> Self::IntoIter {
match self {
Value::Map(v) => v.into_iter(),
Value::Array(arr) => {
let mut v = ValueMap::with_capacity(arr.len());
let mut idx = 0;
for x in arr {
v.insert(Value::U32(idx), x);
idx += 1;
}
v.into_iter()
}
Value::Ext(_, e) => e.into_iter(),
_ => {
let v = ValueMap::with_capacity(0);
v.into_iter()
}
}
}
}
impl<'a> IntoIterator for &'a Value {
type Item = (Value, &'a Value);
type IntoIter = std::vec::IntoIter<(Value, &'a Value)>;
fn into_iter(self) -> Self::IntoIter {
match self {
Value::Map(m) => {
let mut arr = Vec::with_capacity(m.len());
for (k, v) in m {
arr.push((k.to_owned(), v));
}
arr.into_iter()
}
Value::Array(arr) => {
let mut v = Vec::with_capacity(arr.len());
let mut idx = 0;
for x in arr {
v.push((Value::U32(idx), x));
idx += 1;
}
v.into_iter()
}
Value::Ext(_, e) => e.deref().into_iter(),
_ => {
let v = Vec::with_capacity(0);
v.into_iter()
}
}
}
}
impl<'a, 'b> IntoIterator for &'a &'b Value {
type Item = (Value, &'b Value);
type IntoIter = std::vec::IntoIter<(Value, &'b Value)>;
fn into_iter(self) -> Self::IntoIter {
(*self).into_iter()
}
}
impl From<Value> for bool {
fn from(arg: Value) -> Self {
arg.as_bool().unwrap_or_default()
}
}
impl From<&Value> for bool {
fn from(arg: &Value) -> Self {
arg.as_bool().unwrap_or_default()
}
}
impl From<Value> for f64 {
fn from(arg: Value) -> Self {
arg.as_f64().unwrap_or_default()
}
}
impl From<&Value> for f64 {
fn from(arg: &Value) -> Self {
arg.as_f64().unwrap_or_default()
}
}
impl From<Value> for i64 {
fn from(arg: Value) -> Self {
arg.as_i64().unwrap_or_default()
}
}
impl From<&Value> for i64 {
fn from(arg: &Value) -> Self {
arg.as_i64().unwrap_or_default()
}
}
impl From<Value> for u64 {
fn from(arg: Value) -> Self {
arg.as_u64().unwrap_or_default()
}
}
impl From<&Value> for u64 {
fn from(arg: &Value) -> Self {
arg.as_u64().unwrap_or_default()
}
}
impl From<Value> for String {
fn from(arg: Value) -> Self {
arg.as_str().unwrap_or_default().to_string()
}
}
impl From<&Value> for String {
fn from(arg: &Value) -> Self {
arg.as_str().unwrap_or_default().to_string()
}
}
impl Eq for Value {}
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Value::Null => {
state.write_u8(0);
}
Value::Bool(b) => {
state.write_u8(1);
b.hash(state);
}
Value::I32(i) => {
state.write_u8(2);
i.hash(state);
}
Value::I64(i) => {
state.write_u8(3);
i.hash(state);
}
Value::U32(u) => {
state.write_u8(4);
u.hash(state);
}
Value::U64(u) => {
state.write_u8(5);
u.hash(state);
}
Value::F32(f) => {
state.write_u8(6);
f.to_bits().hash(state);
}
Value::F64(f) => {
state.write_u8(7);
f.to_bits().hash(state);
}
Value::String(s) => {
state.write_u8(8);
s.hash(state);
}
Value::Binary(b) => {
state.write_u8(9);
b.hash(state);
}
Value::Array(a) => {
state.write_u8(10);
for v in a {
v.hash(state);
}
}
Value::Map(m) => {
state.write_u8(11);
for (k, v) in m {
k.hash(state);
v.hash(state);
}
}
Value::Ext(_, v) => {
state.write_u8(12);
v.hash(state);
}
}
}
}
#[cfg(test)]
mod test {
use crate::Value;
use std::collections::HashMap;
#[test]
fn test_display() {
let v = Value::U64(1);
println!("{}", v);
assert_eq!("1", v.to_string());
}
#[test]
fn test_iter() {
let v = Value::Array(vec![Value::I32(1), Value::I32(2), Value::I32(3)]);
for (k, v) in &v {
if Value::I32(1).eq(v) {
assert_eq!(&Value::U32(0), &k);
}
if Value::I32(2).eq(v) {
assert_eq!(&Value::U32(1), &k);
}
if Value::I32(3).eq(v) {
assert_eq!(&Value::U32(2), &k);
}
}
}
#[test]
fn test_hashmap() {
let mut v = HashMap::new();
v.insert(Value::F32(1.1), Value::I32(1));
v.insert(Value::F32(1.2), Value::I32(2));
assert_eq!(v.get(&Value::F32(1.1)).unwrap(), &Value::I32(1));
}
}