#![warn(unused_extern_crates)]
#![deny(
clippy::all,
clippy::unwrap_used,
clippy::unnecessary_unwrap,
clippy::pedantic
)]
#![allow(clippy::module_name_repetitions, clippy::inline_always)]
#![allow(clippy::type_repetition_in_bounds)]
#![deny(missing_docs)]
#[cfg(all(feature = "128bit", feature = "c-abi"))]
compile_error!(
"Combining the features `128bit` and `c-abi` is impossible because i128's \
ABI is unstable (see \
https://github.com/rust-lang/unsafe-code-guidelines/issues/119). Please \
use only one of them in order to compile this crate. If you don't know \
where this error is coming from, it's possible that you depend on \
value-trait twice indirectly, once with the `c-abi` feature, and once with \
the `128bit` feature, and that they have been merged by Cargo."
);
use std::borrow::{Borrow, Cow};
use std::convert::TryInto;
use std::fmt;
use std::hash::Hash;
use std::io::{self, Write};
use std::ops::{Index, IndexMut};
mod array;
pub mod generator;
mod node;
mod object;
mod option;
pub mod prelude;
pub use array::Array;
pub use node::StaticNode;
pub use object::Object;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessError {
NotAnObject,
NotAnArray,
}
#[cfg(not(tarpaulin_include))]
impl fmt::Display for AccessError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotAnArray => write!(f, "The value is not an array"),
Self::NotAnObject => write!(f, "The value is not an object"),
}
}
}
impl std::error::Error for AccessError {}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ExtendedValueType {
I32,
I16,
I8,
U32,
U16,
U8,
Usize,
F32,
Char,
None,
}
impl Default for ExtendedValueType {
fn default() -> Self {
Self::None
}
}
impl fmt::Display for ExtendedValueType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::I32 => write!(f, "i32"),
Self::I16 => write!(f, "i16"),
Self::I8 => write!(f, "i8"),
Self::U32 => write!(f, "u32"),
Self::U16 => write!(f, "u16"),
Self::U8 => write!(f, "u8"),
Self::Usize => write!(f, "usize"),
Self::F32 => write!(f, "f32"),
Self::Char => write!(f, "char"),
Self::None => write!(f, "none"),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ValueType {
Null,
Bool,
I64,
I128,
U64,
U128,
F64,
String,
Array,
Object,
Extended(ExtendedValueType),
#[cfg(feature = "custom-types")]
Custom(&'static str),
}
impl fmt::Display for ValueType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Null => write!(f, "null"),
Self::Bool => write!(f, "bool"),
Self::I64 => write!(f, "i64"),
Self::I128 => write!(f, "i128"),
Self::U64 => write!(f, "u64"),
Self::U128 => write!(f, "u128"),
Self::F64 => write!(f, "f64"),
Self::String => write!(f, "string"),
Self::Array => write!(f, "array"),
Self::Object => write!(f, "object"),
Self::Extended(ty) => write!(f, "{}", ty),
#[cfg(feature = "custom-types")]
Self::Custom(name) => write!(f, "{}", name),
}
}
}
impl Default for ValueType {
fn default() -> Self {
Self::Null
}
}
pub trait Writable {
#[must_use]
fn encode(&self) -> String;
#[must_use]
fn encode_pp(&self) -> String;
fn write<'writer, W>(&self, w: &mut W) -> io::Result<()>
where
W: 'writer + Write;
fn write_pp<'writer, W>(&self, w: &mut W) -> io::Result<()>
where
W: 'writer + Write;
}
#[allow(clippy::trait_duplication_in_bounds)] pub trait Builder<'input>:
Default
+ From<StaticNode>
+ From<i8>
+ From<i16>
+ From<i32>
+ From<i64>
+ From<u8>
+ From<u16>
+ From<u32>
+ From<u64>
+ From<f32>
+ From<f64>
+ From<bool>
+ From<()>
+ From<String>
+ From<&'input str>
+ From<Cow<'input, str>>
{
fn array_with_capacity(capacity: usize) -> Self;
fn object_with_capacity(capacity: usize) -> Self;
#[must_use]
fn array() -> Self {
Self::array_with_capacity(0)
}
#[must_use]
fn object() -> Self {
Self::object_with_capacity(0)
}
fn null() -> Self;
}
#[derive(Clone, Debug)]
pub struct TryTypeError {
pub expected: ValueType,
pub got: ValueType,
}
impl std::fmt::Display for TryTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Expected type {}, got {}", self.expected, self.got)
}
}
impl std::error::Error for TryTypeError {}
pub trait ValueInto: Sized + ValueAccess {
type String;
#[must_use]
fn into_string(self) -> Option<Self::String>;
#[inline]
fn try_into_string(self) -> Result<Self::String, TryTypeError> {
let vt = self.value_type();
self.into_string().ok_or(TryTypeError {
expected: ValueType::String,
got: vt,
})
}
#[must_use]
fn into_array(self) -> Option<Self::Array>;
#[inline]
fn try_into_array(self) -> Result<Self::Array, TryTypeError> {
let vt = self.value_type();
self.into_array().ok_or(TryTypeError {
expected: ValueType::Array,
got: vt,
})
}
#[must_use]
fn into_object(self) -> Option<Self::Object>;
#[inline]
fn try_into_object(self) -> Result<Self::Object, TryTypeError> {
let vt = self.value_type();
self.into_object().ok_or(TryTypeError {
expected: ValueType::Object,
got: vt,
})
}
}
pub trait ValueAccess: Sized {
type Target: ValueAccess;
type Key: Hash + Eq;
type Array: Array<Element = Self::Target>;
type Object: Object<Key = Self::Key, Element = Self::Target>;
#[must_use]
fn value_type(&self) -> ValueType;
#[must_use]
fn as_bool(&self) -> Option<bool>;
#[inline]
fn try_as_bool(&self) -> Result<bool, TryTypeError> {
self.as_bool().ok_or(TryTypeError {
expected: ValueType::Bool,
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_i128(&self) -> Option<i128> {
self.as_i64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_i128(&self) -> Result<i128, TryTypeError> {
self.as_i128().ok_or(TryTypeError {
expected: ValueType::I128,
got: self.value_type(),
})
}
#[must_use]
fn as_i64(&self) -> Option<i64>;
#[inline]
fn try_as_i64(&self) -> Result<i64, TryTypeError> {
self.as_i64().ok_or(TryTypeError {
expected: ValueType::I64,
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_i32(&self) -> Option<i32> {
self.as_i64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_i32(&self) -> Result<i32, TryTypeError> {
self.as_i32().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::I32),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_i16(&self) -> Option<i16> {
self.as_i64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_i16(&self) -> Result<i16, TryTypeError> {
self.as_i16().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::I16),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_i8(&self) -> Option<i8> {
self.as_i64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_i8(&self) -> Result<i8, TryTypeError> {
self.as_i8().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::I8),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_u128(&self) -> Option<u128> {
self.as_u64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_u128(&self) -> Result<u128, TryTypeError> {
self.as_u128().ok_or(TryTypeError {
expected: ValueType::U128,
got: self.value_type(),
})
}
#[must_use]
fn as_u64(&self) -> Option<u64>;
#[inline]
fn try_as_u64(&self) -> Result<u64, TryTypeError> {
self.as_u64().ok_or(TryTypeError {
expected: ValueType::U64,
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_usize(&self) -> Option<usize> {
self.as_u64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_usize(&self) -> Result<usize, TryTypeError> {
self.as_usize().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::Usize),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_u32(&self) -> Option<u32> {
self.as_u64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_u32(&self) -> Result<u32, TryTypeError> {
self.as_u32().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::U32),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_u16(&self) -> Option<u16> {
self.as_u64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_u16(&self) -> Result<u16, TryTypeError> {
self.as_u16().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::U16),
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_u8(&self) -> Option<u8> {
self.as_u64().and_then(|u| u.try_into().ok())
}
#[inline]
fn try_as_u8(&self) -> Result<u8, TryTypeError> {
self.as_u8().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::U8),
got: self.value_type(),
})
}
#[must_use]
fn as_f64(&self) -> Option<f64>;
#[inline]
fn try_as_f64(&self) -> Result<f64, TryTypeError> {
self.as_f64().ok_or(TryTypeError {
expected: ValueType::F64,
got: self.value_type(),
})
}
#[must_use]
#[inline]
#[allow(clippy::cast_precision_loss, clippy::option_if_let_else)]
fn cast_f64(&self) -> Option<f64> {
if let Some(f) = self.as_f64() {
Some(f)
} else if let Some(u) = self.as_u128() {
Some(u as f64)
} else {
self.as_i128().map(|i| i as f64)
}
}
#[inline]
#[allow(clippy::cast_precision_loss, clippy::option_if_let_else)]
fn try_cast_f64(&self) -> Result<f64, TryTypeError> {
if let Some(f) = self.as_f64() {
Ok(f)
} else if let Some(u) = self.as_u128() {
Ok(u as f64)
} else {
self.try_as_i128().map(|i| i as f64)
}
}
#[allow(clippy::cast_possible_truncation)]
#[inline]
#[must_use]
fn as_f32(&self) -> Option<f32> {
self.as_f64().and_then(|u| {
if u <= f64::from(std::f32::MAX) && u >= f64::from(std::f32::MIN) {
Some(u as f32)
} else {
None
}
})
}
#[inline]
fn try_as_f32(&self) -> Result<f32, TryTypeError> {
self.as_f32().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::F32),
got: self.value_type(),
})
}
#[must_use]
fn as_str(&self) -> Option<&str>;
#[inline]
fn try_as_str(&self) -> Result<&str, TryTypeError> {
self.as_str().ok_or(TryTypeError {
expected: ValueType::String,
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn as_char(&self) -> Option<char> {
self.as_str().and_then(|s| s.chars().next())
}
#[inline]
fn try_as_char(&self) -> Result<char, TryTypeError> {
self.as_char().ok_or(TryTypeError {
expected: ValueType::Extended(ExtendedValueType::Char),
got: self.value_type(),
})
}
#[must_use]
fn as_array(&self) -> Option<&Self::Array>;
#[inline]
fn try_as_array(&self) -> Result<&Self::Array, TryTypeError> {
self.as_array().ok_or(TryTypeError {
expected: ValueType::Array,
got: self.value_type(),
})
}
#[must_use]
fn as_object(&self) -> Option<&Self::Object>;
#[inline]
fn try_as_object(&self) -> Result<&Self::Object, TryTypeError> {
self.as_object().ok_or(TryTypeError {
expected: ValueType::Object,
got: self.value_type(),
})
}
#[inline]
#[must_use]
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Self::Target>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.as_object().and_then(|a| a.get(k))
}
#[inline]
fn try_get<Q: ?Sized>(&self, k: &Q) -> Result<Option<&Self::Target>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
Ok(self
.as_object()
.ok_or_else(|| TryTypeError {
expected: ValueType::Object,
got: self.value_type(),
})?
.get(k))
}
#[inline]
#[must_use]
fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.as_object().and_then(|a| a.get(k)).is_some()
}
#[inline]
#[must_use]
fn get_idx(&self, i: usize) -> Option<&Self::Target> {
self.as_array().and_then(|a| a.get(i))
}
#[inline]
fn try_get_idx(&self, i: usize) -> Result<Option<&Self::Target>, TryTypeError> {
Ok(self
.as_array()
.ok_or_else(|| TryTypeError {
expected: ValueType::Array,
got: self.value_type(),
})?
.get(i))
}
#[inline]
#[must_use]
fn get_bool<Q: ?Sized>(&self, k: &Q) -> Option<bool>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_bool)
}
#[inline]
fn try_get_bool<Q: ?Sized>(&self, k: &Q) -> Result<Option<bool>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_bool).transpose()
}
#[inline]
#[must_use]
fn get_i128<Q: ?Sized>(&self, k: &Q) -> Option<i128>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_i128)
}
#[inline]
fn try_get_i128<Q: ?Sized>(&self, k: &Q) -> Result<Option<i128>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_i128).transpose()
}
#[inline]
#[must_use]
fn get_i64<Q: ?Sized>(&self, k: &Q) -> Option<i64>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_i64)
}
#[inline]
fn try_get_i64<Q: ?Sized>(&self, k: &Q) -> Result<Option<i64>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_i64).transpose()
}
#[inline]
#[must_use]
fn get_i32<Q: ?Sized>(&self, k: &Q) -> Option<i32>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_i32)
}
#[inline]
fn try_get_i32<Q: ?Sized>(&self, k: &Q) -> Result<Option<i32>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_i32).transpose()
}
#[inline]
#[must_use]
fn get_i16<Q: ?Sized>(&self, k: &Q) -> Option<i16>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_i16)
}
#[inline]
fn try_get_i16<Q: ?Sized>(&self, k: &Q) -> Result<Option<i16>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_i16).transpose()
}
#[inline]
#[must_use]
fn get_i8<Q: ?Sized>(&self, k: &Q) -> Option<i8>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_i8)
}
#[inline]
fn try_get_i8<Q: ?Sized>(&self, k: &Q) -> Result<Option<i8>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_i8).transpose()
}
#[inline]
#[must_use]
fn get_u128<Q: ?Sized>(&self, k: &Q) -> Option<u128>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_u128)
}
#[inline]
fn try_get_u128<Q: ?Sized>(&self, k: &Q) -> Result<Option<u128>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_u128).transpose()
}
#[inline]
#[must_use]
fn get_u64<Q: ?Sized>(&self, k: &Q) -> Option<u64>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_u64)
}
#[inline]
fn try_get_u64<Q: ?Sized>(&self, k: &Q) -> Result<Option<u64>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_u64).transpose()
}
#[inline]
#[must_use]
fn get_usize<Q: ?Sized>(&self, k: &Q) -> Option<usize>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_usize)
}
#[inline]
fn try_get_usize<Q: ?Sized>(&self, k: &Q) -> Result<Option<usize>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_usize).transpose()
}
#[inline]
#[must_use]
fn get_u32<Q: ?Sized>(&self, k: &Q) -> Option<u32>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_u32)
}
#[inline]
fn try_get_u32<Q: ?Sized>(&self, k: &Q) -> Result<Option<u32>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_u32).transpose()
}
#[inline]
#[must_use]
fn get_u16<Q: ?Sized>(&self, k: &Q) -> Option<u16>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_u16)
}
#[inline]
fn try_get_u16<Q: ?Sized>(&self, k: &Q) -> Result<Option<u16>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_u16).transpose()
}
#[inline]
#[must_use]
fn get_u8<Q: ?Sized>(&self, k: &Q) -> Option<u8>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_u8)
}
#[inline]
fn try_get_u8<Q: ?Sized>(&self, k: &Q) -> Result<Option<u8>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_u8).transpose()
}
#[inline]
#[must_use]
fn get_f64<Q: ?Sized>(&self, k: &Q) -> Option<f64>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_f64)
}
#[inline]
fn try_get_f64<Q: ?Sized>(&self, k: &Q) -> Result<Option<f64>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_f64).transpose()
}
#[inline]
#[must_use]
fn get_f32<Q: ?Sized>(&self, k: &Q) -> Option<f32>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_f32)
}
#[inline]
fn try_get_f32<Q: ?Sized>(&self, k: &Q) -> Result<Option<f32>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)?.map(ValueAccess::try_as_f32).transpose()
}
#[inline]
#[must_use]
fn get_str<Q: ?Sized>(&self, k: &Q) -> Option<&str>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_str)
}
#[inline]
fn try_get_str<Q: ?Sized>(&self, k: &Q) -> Result<Option<&str>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)
.and_then(|s| s.map(ValueAccess::try_as_str).transpose())
}
#[inline]
#[must_use]
fn get_array<Q: ?Sized>(
&self,
k: &Q,
) -> Option<&<<Self as ValueAccess>::Target as ValueAccess>::Array>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_array)
}
#[inline]
fn try_get_array<Q: ?Sized>(
&self,
k: &Q,
) -> Result<Option<&<<Self as ValueAccess>::Target as ValueAccess>::Array>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)
.and_then(|s| s.map(ValueAccess::try_as_array).transpose())
}
#[inline]
#[must_use]
fn get_object<Q: ?Sized>(
&self,
k: &Q,
) -> Option<&<<Self as ValueAccess>::Target as ValueAccess>::Object>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.get(k).and_then(ValueAccess::as_object)
}
#[inline]
fn try_get_object<Q: ?Sized>(
&self,
k: &Q,
) -> Result<Option<&<<Self as ValueAccess>::Target as ValueAccess>::Object>, TryTypeError>
where
Self::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.try_get(k)
.and_then(|s| s.map(ValueAccess::try_as_object).transpose())
}
}
pub trait Value:
Sized
+ Index<usize>
+ PartialEq<i8>
+ PartialEq<i16>
+ PartialEq<i32>
+ PartialEq<i64>
+ PartialEq<i128>
+ PartialEq<u8>
+ PartialEq<u16>
+ PartialEq<u32>
+ PartialEq<u64>
+ PartialEq<u128>
+ PartialEq<f32>
+ PartialEq<f64>
+ PartialEq<String>
+ PartialEq<bool>
+ PartialEq<()>
+ ValueAccess
{
#[must_use]
fn is_null(&self) -> bool;
#[inline]
#[must_use]
fn is_float(&self) -> bool {
self.is_f64()
}
#[inline]
#[must_use]
fn is_integer(&self) -> bool {
self.is_i128() || self.is_u128()
}
#[inline]
#[must_use]
fn is_number(&self) -> bool {
self.is_float() || self.is_integer()
}
#[inline]
#[must_use]
fn is_bool(&self) -> bool {
self.as_bool().is_some()
}
#[inline]
#[must_use]
fn is_i128(&self) -> bool {
self.as_i128().is_some()
}
#[inline]
#[must_use]
fn is_i64(&self) -> bool {
self.as_i64().is_some()
}
#[inline]
#[must_use]
fn is_i32(&self) -> bool {
self.as_i32().is_some()
}
#[inline]
#[must_use]
fn is_i16(&self) -> bool {
self.as_i16().is_some()
}
#[inline]
#[must_use]
fn is_i8(&self) -> bool {
self.as_i8().is_some()
}
#[inline]
#[must_use]
fn is_u128(&self) -> bool {
self.as_u128().is_some()
}
#[inline]
#[must_use]
fn is_u64(&self) -> bool {
self.as_u64().is_some()
}
#[inline]
#[must_use]
fn is_usize(&self) -> bool {
self.as_usize().is_some()
}
#[inline]
#[must_use]
fn is_u32(&self) -> bool {
self.as_u32().is_some()
}
#[inline]
#[must_use]
fn is_u16(&self) -> bool {
self.as_u16().is_some()
}
#[inline]
#[must_use]
fn is_u8(&self) -> bool {
self.as_u8().is_some()
}
#[inline]
#[must_use]
fn is_f64(&self) -> bool {
self.as_f64().is_some()
}
#[inline]
#[must_use]
fn is_f64_castable(&self) -> bool {
self.cast_f64().is_some()
}
#[inline]
#[must_use]
fn is_f32(&self) -> bool {
self.as_f32().is_some()
}
#[inline]
#[must_use]
fn is_str(&self) -> bool {
self.as_str().is_some()
}
#[inline]
#[must_use]
fn is_char(&self) -> bool {
self.as_char().is_some()
}
#[inline]
#[must_use]
fn is_array(&self) -> bool {
self.as_array().is_some()
}
#[inline]
#[must_use]
fn is_object(&self) -> bool {
self.as_object().is_some()
}
#[cfg(feature = "custom-types")]
fn is_custom(&self) -> bool {
false
}
}
pub trait Mutable: IndexMut<usize> + Value + Sized {
#[inline]
fn insert<K, V>(&mut self, k: K, v: V) -> std::result::Result<Option<Self::Target>, AccessError>
where
K: Into<<Self as ValueAccess>::Key>,
V: Into<<Self as ValueAccess>::Target>,
<Self as ValueAccess>::Key: Hash + Eq,
{
self.as_object_mut()
.ok_or(AccessError::NotAnObject)
.map(|o| o.insert(k.into(), v.into()))
}
#[inline]
fn try_insert<K, V>(&mut self, k: K, v: V) -> Option<Self::Target>
where
K: Into<<Self as ValueAccess>::Key>,
V: Into<<Self as ValueAccess>::Target>,
<Self as ValueAccess>::Key: Hash + Eq,
{
self.insert(k, v).ok().flatten()
}
#[inline]
fn remove<Q: ?Sized>(&mut self, k: &Q) -> std::result::Result<Option<Self::Target>, AccessError>
where
<Self as ValueAccess>::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.as_object_mut()
.ok_or(AccessError::NotAnObject)
.map(|o| o.remove(k))
}
#[inline]
fn try_remove<Q: ?Sized>(&mut self, k: &Q) -> Option<Self::Target>
where
<Self as ValueAccess>::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.remove(k).ok().flatten()
}
#[inline]
fn push<V>(&mut self, v: V) -> std::result::Result<(), AccessError>
where
V: Into<<Self as ValueAccess>::Target>,
{
self.as_array_mut()
.ok_or(AccessError::NotAnArray)
.map(|o| o.push(v.into()))
}
fn try_push<V>(&mut self, v: V)
where
V: Into<<Self as ValueAccess>::Target>,
{
let _ = self.push(v);
}
#[inline]
fn pop(&mut self) -> std::result::Result<Option<Self::Target>, AccessError> {
self.as_array_mut()
.ok_or(AccessError::NotAnArray)
.map(Array::pop)
}
#[inline]
fn try_pop(&mut self) -> Option<Self::Target> {
self.pop().ok().flatten()
}
fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut Self::Target>
where
<Self as ValueAccess>::Key: Borrow<Q> + Hash + Eq,
Q: Hash + Eq + Ord,
{
self.as_object_mut().and_then(|m| m.get_mut(k))
}
#[inline]
fn get_idx_mut(&mut self, i: usize) -> Option<&mut Self::Target> {
self.as_array_mut().and_then(|a| a.get_mut(i))
}
fn as_array_mut(&mut self) -> Option<&mut <Self as ValueAccess>::Array>;
fn as_object_mut(&mut self) -> Option<&mut Self::Object>;
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}