use imbl::Vector;
use index::Index;
use serde::{de::DeserializeOwned, Serialize};
use std::{
fmt::{self, Debug, Display},
io,
sync::Arc,
};
pub mod de;
mod from;
pub mod in_order_map;
pub mod index;
pub mod macros;
pub mod ser;
#[cfg(feature = "arbitrary")]
mod arbitrary;
#[cfg(feature = "ts-rs")]
mod ts_rs;
pub use imbl;
pub use in_order_map::InOMap;
pub use serde_json::Error as ErrorSource;
pub use serde_json::Number;
pub use yasi::InternedString;
pub const NULL: Value = Value::Null;
#[derive(Debug)]
pub enum ErrorKind {
Serialization,
Deserialization,
}
#[derive(Debug)]
pub struct Error {
pub kind: ErrorKind,
pub source: ErrorSource,
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?} Error: {}", self.kind, self.source)
}
}
impl std::error::Error for Error {}
#[derive(Clone)]
pub enum Value {
Null,
Bool(bool),
Number(Number),
String(Arc<String>),
Array(Vector<Value>),
Object(InOMap<InternedString, Value>),
}
impl Debug for Value {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Value::Null => formatter.write_str("Null"),
Value::Bool(boolean) => write!(formatter, "Bool({})", boolean),
Value::Number(number) => Debug::fmt(number, formatter),
Value::String(string) => write!(formatter, "String({:?})", string),
Value::Array(vec) => {
formatter.write_str("Array ")?;
Debug::fmt(vec, formatter)
}
Value::Object(map) => {
formatter.write_str("Object ")?;
Debug::fmt(map, formatter)
}
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
struct WriterFormatter<'a, 'b: 'a> {
inner: &'a mut fmt::Formatter<'b>,
}
impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let s = unsafe { String::from_utf8_unchecked(buf.to_owned()) };
self.inner.write_str(&s).map_err(io_error)?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn io_error(_: fmt::Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, "fmt error")
}
let alternate = f.alternate();
let mut wr = WriterFormatter { inner: f };
if alternate {
serde_json::ser::to_writer_pretty(&mut wr, self).map_err(|_| fmt::Error)
} else {
serde_json::ser::to_writer(&mut wr, self).map_err(|_| fmt::Error)
}
}
}
fn parse_index(s: &str) -> Option<usize> {
if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) {
return None;
}
s.parse().ok()
}
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_object(&self) -> bool {
self.as_object().is_some()
}
pub fn as_object(&self) -> Option<&InOMap<InternedString, Value>> {
match self {
Value::Object(map) => Some(map),
_ => None,
}
}
pub fn as_object_mut(&mut self) -> Option<&mut InOMap<InternedString, Value>> {
match self {
Value::Object(map) => Some(map),
_ => None,
}
}
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub fn as_array(&self) -> Option<&Vector<Value>> {
match self {
Value::Array(array) => Some(array),
_ => None,
}
}
pub fn as_array_mut(&mut self) -> Option<&mut Vector<Value>> {
match self {
Value::Array(list) => Some(list),
_ => 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_number(&self) -> bool {
match *self {
Value::Number(_) => true,
_ => false,
}
}
pub fn is_i64(&self) -> bool {
match self {
Value::Number(n) => n.is_i64(),
_ => false,
}
}
pub fn is_u64(&self) -> bool {
match self {
Value::Number(n) => n.is_u64(),
_ => false,
}
}
pub fn is_f64(&self) -> bool {
match self {
Value::Number(n) => n.is_f64(),
_ => false,
}
}
pub fn as_i64(&self) -> Option<i64> {
match self {
Value::Number(n) => n.as_i64(),
_ => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
match self {
Value::Number(n) => n.as_u64(),
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Value::Number(n) => n.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 pointer(&self, pointer: &str) -> Option<&Value> {
if pointer.is_empty() {
return Some(self);
}
if !pointer.starts_with('/') {
return None;
}
pointer
.split('/')
.skip(1)
.map(|x| x.replace("~1", "/").replace("~0", "~"))
.map(Arc::new)
.try_fold(self, |target, token| match target {
Value::Object(map) => map.get(&**token),
Value::Array(list) => parse_index(&token).and_then(|x| list.get(x)),
_ => None,
})
}
pub fn pointer_mut(&mut self, pointer: &str) -> Option<&mut Value> {
if pointer.is_empty() {
return Some(self);
}
if !pointer.starts_with('/') {
return None;
}
pointer
.split('/')
.skip(1)
.map(|x| x.replace("~1", "/").replace("~0", "~"))
.map(Arc::new)
.try_fold(self, |target, token| match target {
Value::Object(map) => map.get_mut(&**token),
Value::Array(list) => parse_index(&token).and_then(move |x| list.get_mut(x)),
_ => None,
})
}
pub fn take(&mut self) -> Value {
::std::mem::replace(self, Value::Null)
}
pub fn ptr_eq(&self, other: &Value) -> bool {
match (self, other) {
(Self::Array(a), Self::Array(b)) => a.ptr_eq(b),
(Self::Object(a), Self::Object(b)) => a.ptr_eq(b),
(Self::String(a), Self::String(b)) => Arc::ptr_eq(a, b),
(a, b) => a == b, }
}
}
impl Default for Value {
fn default() -> Value {
Value::Null
}
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Value::Array(a), Value::Array(b)) => a.ptr_eq(b) || a == b,
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::Null, Value::Null) => true,
(Value::Number(a), Value::Number(b)) => a == b,
(Value::Object(a), Value::Object(b)) => a.ptr_eq(b) || a == b,
(Value::String(a), Value::String(b)) => Arc::ptr_eq(a, b) || a == b,
_ => false,
}
}
}
impl Eq for Value {}
impl PartialEq<f64> for Value {
fn eq(&self, other: &f64) -> bool {
match self {
Value::Number(n) => n.as_f64() == Some(*other),
_ => false,
}
}
}
impl PartialEq<i64> for Value {
fn eq(&self, other: &i64) -> bool {
match self {
Value::Number(n) => n.as_i64() == Some(*other),
_ => false,
}
}
}
impl PartialEq<u64> for Value {
fn eq(&self, other: &u64) -> bool {
match self {
Value::Number(n) => n.as_u64() == Some(*other),
_ => false,
}
}
}
impl PartialEq<str> for Value {
fn eq(&self, other: &str) -> bool {
match self {
Value::String(s) => &**s == other,
_ => false,
}
}
}
pub fn to_value<T>(value: &T) -> Result<Value, Error>
where
T: Serialize,
{
value.serialize(ser::Serializer).map_err(|e| Error {
kind: ErrorKind::Serialization,
source: e,
})
}
pub fn from_value<T>(value: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
T::deserialize(value).map_err(|e| Error {
kind: ErrorKind::Deserialization,
source: e,
})
}
#[test]
fn test_serialize_loop() {
let value = json!({
"a": "hello I'm a",
"b": 1,
"c": true,
"d": null,
"e": [123, "testing"],
"f": { "h": 'i'}
});
assert_eq!(
&serde_json::to_string(&value)
.unwrap(),
"{\"a\":\"hello I'm a\",\"b\":1,\"c\":true,\"d\":null,\"e\":[123,\"testing\"],\"f\":{\"h\":\"i\"}}"
);
assert_eq!(
value,
serde_json::from_str::<Value>(&serde_json::to_string(&value).unwrap()).unwrap(),
);
assert_eq!(value["f"]["h"].as_str().unwrap(), "i");
}