use std::{
fmt::{self, Write},
mem,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
mod de;
mod error;
mod from;
mod index;
mod number;
mod partial_eq;
mod ser;
pub mod map;
pub use self::error::Error;
pub use self::index::Index;
pub use self::map::Map;
pub use self::number::Number;
#[derive(Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub enum Value {
#[default]
Null,
Bool(bool),
Number(Number),
String(String),
ByteArray(Vec<u8>),
Array(Vec<Value>),
Map(Map<String, Value>),
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Value::Null => f.write_str("Null"),
Value::Bool(boolean) => f.debug_tuple("Bool").field(boolean).finish(),
Value::Number(number) => fmt::Debug::fmt(number, f),
Value::String(string) => f.debug_tuple("String").field(string).finish(),
Value::ByteArray(bytes) => f
.debug_tuple("ByteArray")
.field(&DebugByteArray(bytes))
.finish(),
Value::Array(vec) => f.debug_tuple("Array").field(vec).finish(),
Value::Map(map) => f.debug_tuple("Map").field(map).finish(),
}
}
}
struct DebugByteArray<'a>(&'a [u8]);
impl fmt::Debug for DebugByteArray<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
for chunk in self.0.utf8_chunks() {
{
let valid = chunk.valid();
let mut from = 0;
for (i, c) in valid.char_indices() {
let esc = c.escape_debug();
if esc.len() != 1 {
f.write_str(&valid[from..i])?;
for c in esc {
f.write_char(c)?;
}
from = i + c.len_utf8();
}
}
f.write_str(&valid[from..])?;
}
for &b in chunk.invalid() {
write!(f, "\\x{:02X}", b)?;
}
}
f.write_char('"')
}
}
impl Value {
pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
index.index_into(self)
}
pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> {
index.index_into_mut(self)
}
pub fn is_map(&self) -> bool {
self.as_map().is_some()
}
pub fn as_map(&self) -> Option<&Map<String, Value>> {
match self {
Value::Map(map) => Some(map),
_ => None,
}
}
pub fn as_map_mut(&mut self) -> Option<&mut Map<String, Value>> {
match self {
Value::Map(map) => Some(map),
_ => None,
}
}
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub fn as_array(&self) -> Option<&Vec<Value>> {
match self {
Value::Array(vec) => Some(vec),
_ => None,
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
match self {
Value::Array(vec) => Some(vec),
_ => None,
}
}
pub fn is_string(&self) -> bool {
self.as_str().is_some()
}
pub fn as_str(&self) -> Option<&str> {
match self {
Value::String(s) => Some(s),
_ => None,
}
}
pub fn is_bytes(&self) -> bool {
self.as_bytes().is_some()
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
Value::ByteArray(bytes) => Some(bytes),
_ => None,
}
}
pub fn is_number(&self) -> bool {
self.as_number().is_some()
}
pub fn as_number(&self) -> Option<&Number> {
match self {
Value::Number(number) => Some(number),
_ => None,
}
}
pub fn is_i64(&self) -> bool {
match self {
Value::Number(number) => number.is_i64(),
_ => false,
}
}
pub fn is_u64(&self) -> bool {
match self {
Value::Number(number) => number.is_u64(),
_ => false,
}
}
pub fn is_f64(&self) -> bool {
match self {
Value::Number(number) => number.is_f64(),
_ => false,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Number(number) => number.as_i64(),
_ => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match self {
Value::Number(number) => number.as_u64(),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Value::Number(number) => number.as_f64(),
_ => None,
}
}
pub fn is_boolean(&self) -> bool {
self.as_bool().is_some()
}
pub fn as_bool(&self) -> Option<bool> {
match *self {
Value::Bool(b) => Some(b),
_ => None,
}
}
pub fn is_null(&self) -> bool {
self.as_null().is_some()
}
pub fn as_null(&self) -> Option<()> {
match *self {
Value::Null => Some(()),
_ => None,
}
}
pub fn take(&mut self) -> Value {
mem::replace(self, Value::Null)
}
}
impl Value {
pub fn from_bytes<B>(bytes: B) -> Value
where
B: Into<Vec<u8>>,
{
Value::ByteArray(bytes.into())
}
}
#[doc(hidden)]
pub fn to_value<T>(value: T) -> Result<Value, Error>
where
T: Serialize,
{
value.serialize(ser::Serializer)
}
#[doc(hidden)]
pub fn from_value<T>(value: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
T::deserialize(value)
}
#[doc(hidden)]
pub fn from_value_borrowed<'de, T>(value: &'de Value) -> Result<T, Error>
where
T: Deserialize<'de>,
{
T::deserialize(value)
}