mod cmp;
mod from;
mod serialize;
use crate::value::{ValueTrait, ValueType};
use crate::{stry, unlikely, Deserializer, ErrorType, Result};
use halfbrown::HashMap;
use std::fmt;
use std::ops::Index;
#[deprecated(since = "0.1.21", note = "Please use Object instead")]
pub type Map = Object;
pub type Object = HashMap<String, Value>;
pub fn to_value(s: &mut [u8]) -> Result<Value> {
let de = stry!(Deserializer::from_slice(s));
OwnedDeserializer::from_deserializer(de).parse()
}
#[derive(Debug, PartialEq, Clone)]
pub enum Value {
Null,
Bool(bool),
F64(f64),
I64(i64),
String(String),
Array(Vec<Value>),
Object(Object),
}
impl ValueTrait for Value {
type Object = Object;
type Array = Vec<Self>;
fn get(&self, k: &str) -> Option<&Self> {
self.as_object().and_then(|a| a.get(k))
}
fn get_mut(&mut self, k: &str) -> Option<&mut Self> {
self.as_object_mut().and_then(|a| a.get_mut(k))
}
fn get_idx(&self, i: usize) -> Option<&Self> {
self.as_array().and_then(|a| a.get(i))
}
fn get_idx_mut(&mut self, i: usize) -> Option<&mut Self> {
self.as_array_mut().and_then(|a| a.get_mut(i))
}
fn value_type(&self) -> ValueType {
match self {
Self::Null => ValueType::Null,
Self::Bool(_) => ValueType::Bool,
Self::F64(_) => ValueType::F64,
Self::I64(_) => ValueType::I64,
Self::String(_) => ValueType::String,
Self::Array(_) => ValueType::Array,
Self::Object(_) => ValueType::Object,
}
}
fn is_null(&self) -> bool {
match self {
Self::Null => true,
_ => false,
}
}
fn as_bool(&self) -> Option<bool> {
match self {
Self::Bool(b) => Some(*b),
_ => None,
}
}
fn as_i64(&self) -> Option<i64> {
match self {
Self::I64(i) => Some(*i),
_ => None,
}
}
fn as_u64(&self) -> Option<u64> {
#[allow(clippy::cast_sign_loss)]
match self {
Self::I64(i) if *i >= 0 => Some(*i as u64),
_ => None,
}
}
fn as_f64(&self) -> Option<f64> {
match self {
Self::F64(i) => Some(*i),
_ => None,
}
}
fn cast_f64(&self) -> Option<f64> {
#[allow(clippy::cast_precision_loss)]
match self {
Self::F64(i) => Some(*i),
Self::I64(i) => Some(*i as f64),
_ => None,
}
}
fn as_string(&self) -> Option<String> {
match self {
Self::String(s) => Some(s.clone()),
_ => None,
}
}
fn as_str(&self) -> Option<&str> {
match self {
Self::String(s) => Some(s.as_str()),
_ => None,
}
}
fn as_array(&self) -> Option<&Vec<Self>> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
fn as_array_mut(&mut self) -> Option<&mut Vec<Self>> {
match self {
Self::Array(a) => Some(a),
_ => None,
}
}
fn as_object(&self) -> Option<&<Self as ValueTrait>::Object> {
match self {
Self::Object(m) => Some(m),
_ => None,
}
}
fn as_object_mut(&mut self) -> Option<&mut <Self as ValueTrait>::Object> {
match self {
Self::Object(m) => Some(m),
_ => None,
}
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Null => f.write_str("null"),
Self::Bool(false) => f.write_str("false"),
Self::Bool(true) => f.write_str("true"),
Self::I64(n) => f.write_str(&n.to_string()),
Self::F64(n) => f.write_str(&n.to_string()),
Self::String(s) => write!(f, "{}", s),
Self::Array(a) => write!(f, "{:?}", a),
Self::Object(o) => write!(f, "{:?}", o),
}
}
}
impl Index<&str> for Value {
type Output = Self;
fn index(&self, index: &str) -> &Self {
static NULL: Value = Value::Null;
self.get(index).unwrap_or(&NULL)
}
}
impl Default for Value {
fn default() -> Self {
Self::Null
}
}
struct OwnedDeserializer<'de> {
de: Deserializer<'de>,
}
impl<'de> OwnedDeserializer<'de> {
pub fn from_deserializer(de: Deserializer<'de>) -> Self {
Self { de }
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
pub fn parse(&mut self) -> Result<Value> {
match self.de.next_() {
b'"' => self.de.parse_str_().map(Value::from),
b'n' => Ok(Value::Null),
b't' => Ok(Value::Bool(true)),
b'f' => Ok(Value::Bool(false)),
b'-' => self.de.parse_number_root(true).map(Value::from),
b'0'..=b'9' => self.de.parse_number_root(false).map(Value::from),
b'[' => self.parse_array(),
b'{' => self.parse_map(),
_c => Err(self.de.error(ErrorType::UnexpectedCharacter)),
}
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
fn parse_value(&mut self) -> Result<Value> {
match self.de.next_() {
b'"' => self.de.parse_str_().map(Value::from),
b'n' => Ok(Value::Null),
b't' => Ok(Value::Bool(true)),
b'f' => Ok(Value::Bool(false)),
b'-' => self.de.parse_number(true).map(Value::from),
b'0'..=b'9' => self.de.parse_number(false).map(Value::from),
b'[' => self.parse_array(),
b'{' => self.parse_map(),
_c => Err(self.de.error(ErrorType::UnexpectedCharacter)),
}
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
fn parse_array(&mut self) -> Result<Value> {
let es = self.de.count_elements();
if unlikely!(es == 0) {
self.de.skip();
return Ok(Value::Array(Vec::new()));
}
let mut res = Vec::with_capacity(es);
for _i in 0..es {
res.push(stry!(self.parse_value()));
self.de.skip();
}
Ok(Value::Array(res))
}
#[cfg_attr(not(feature = "no-inline"), inline(always))]
fn parse_map(&mut self) -> Result<Value> {
let es = self.de.count_elements();
if unlikely!(es == 0) {
self.de.skip();
return Ok(Value::Object(Object::new()));
}
let mut res = Object::with_capacity(es);
for _ in 0..es {
self.de.skip();
let key = stry!(self.de.parse_str_());
self.de.skip();
res.insert_nocheck(key.into(), stry!(self.parse_value()));
self.de.skip();
}
Ok(Value::Object(res))
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn conversions_i64() {
let v = Value::from(i64::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
let v = Value::from(i64::min_value());
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(!v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_i32() {
let v = Value::from(i32::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
let v = Value::from(i32::min_value());
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_i16() {
let v = Value::from(i16::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
let v = Value::from(i16::min_value());
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_i8() {
let v = Value::from(i8::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
let v = Value::from(i8::min_value());
assert!(v.is_i128());
assert!(!v.is_u128());
assert!(v.is_i64());
assert!(!v.is_u64());
assert!(v.is_i32());
assert!(!v.is_u32());
assert!(v.is_i16());
assert!(!v.is_u16());
assert!(v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_u64() {
let v = Value::from(u64::min_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(v.is_i8());
assert!(v.is_u8());
}
#[test]
fn conversions_u32() {
let v = Value::from(u32::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(!v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(!v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_u16() {
let v = Value::from(u16::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(!v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(!v.is_u8());
}
#[test]
fn conversions_u8() {
let v = Value::from(u8::max_value());
assert!(v.is_i128());
assert!(v.is_u128());
assert!(v.is_i64());
assert!(v.is_u64());
assert!(v.is_i32());
assert!(v.is_u32());
assert!(v.is_i16());
assert!(v.is_u16());
assert!(!v.is_i8());
assert!(v.is_u8());
}
}