use std::{
borrow::{Borrow, Cow},
hash::Hash,
io::{self, Write},
};
use value_trait::{
base::{
TypedValue, ValueAsArray as _, ValueAsMutArray, ValueAsMutObject, ValueAsObject as _,
ValueAsScalar, ValueIntoString, Writable,
},
derived::{
ValueArrayTryAccess, ValueObjectAccessAsArray as _, ValueObjectAccessAsObject as _,
ValueObjectAccessAsScalar, ValueObjectAccessTryAsArray as _,
ValueObjectAccessTryAsObject as _, ValueObjectAccessTryAsScalar, ValueObjectTryAccess,
ValueTryAsScalar,
},
TryTypeError, ValueBuilder, ValueType,
};
use crate::{borrowed, tape};
use super::{Array, Object, Value};
impl<'value> ValueBuilder<'value> for Value<'static, 'static, 'value> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn null() -> Self {
Value::Tape(tape::Value::null())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn array_with_capacity(capacity: usize) -> Self {
Value::Value(Cow::Owned(borrowed::Value::array_with_capacity(capacity)))
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn object_with_capacity(capacity: usize) -> Self {
Value::Value(Cow::Owned(borrowed::Value::object_with_capacity(capacity)))
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input>
where
'input: 'tape,
{
#[must_use]
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
#[must_use]
pub fn is_object(&self) -> bool {
self.as_object().is_some()
}
}
impl<'borrow, 'tape, 'value> ValueAsScalar for Value<'borrow, 'tape, 'value> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_null(&self) -> Option<()> {
match &self {
Value::Tape(tape) => tape.as_null(),
Value::Value(value) => value.as_null(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_bool(&self) -> Option<bool> {
match &self {
Value::Tape(tape) => tape.as_bool(),
Value::Value(value) => value.as_bool(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_i64(&self) -> Option<i64> {
match &self {
Value::Tape(tape) => tape.as_i64(),
Value::Value(value) => value.as_i64(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_i128(&self) -> Option<i128> {
match &self {
Value::Tape(tape) => tape.as_i128(),
Value::Value(value) => value.as_i128(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_u64(&self) -> Option<u64> {
match &self {
Value::Tape(tape) => tape.as_u64(),
Value::Value(value) => value.as_u64(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_u128(&self) -> Option<u128> {
match &self {
Value::Tape(tape) => tape.as_u128(),
Value::Value(value) => value.as_u128(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_f64(&self) -> Option<f64> {
match &self {
Value::Tape(tape) => tape.as_f64(),
Value::Value(value) => value.as_f64(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn cast_f64(&self) -> Option<f64> {
match &self {
Value::Tape(tape) => tape.cast_f64(),
Value::Value(value) => value.cast_f64(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_str(&self) -> Option<&str> {
match &self {
Value::Tape(tape) => tape.as_str(),
Value::Value(value) => value.as_str(),
}
}
}
impl<'borrow, 'tape, 'value> ValueIntoString for Value<'borrow, 'tape, 'value> {
type String = Cow<'value, str>;
fn into_string(self) -> Option<<Self as ValueIntoString>::String> {
match self {
Value::Tape(tape) => tape.into_string().map(Cow::Borrowed),
Value::Value(value) => match value {
Cow::Borrowed(value) => match value {
#[cfg(feature = "beef")]
borrowed::Value::String(s) => Some(s.clone().into()),
#[cfg(not(feature = "beef"))]
borrowed::Value::String(s) => Some(s.clone()),
_ => None,
},
Cow::Owned(value) => match value {
#[cfg(feature = "beef")]
borrowed::Value::String(s) => Some(s.into()),
#[cfg(not(feature = "beef"))]
borrowed::Value::String(s) => Some(s),
_ => None,
},
},
}
}
}
impl<'borrow, 'tape, 'input> TypedValue for Value<'borrow, 'tape, 'input> {
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn value_type(&self) -> ValueType {
match &self {
Value::Tape(tape) => tape.value_type(),
Value::Value(value) => value.value_type(),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
pub fn try_get<Q>(&self, k: &Q) -> Result<Option<Value<'_, 'tape, 'input>>, TryTypeError>
where
str: Borrow<Q> + Hash + Eq,
for<'b> crate::cow::Cow<'b, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => Ok(tape.try_get(k)?.map(Value::Tape)),
Value::Value(value) => Ok(value.try_get(k)?.map(Cow::Borrowed).map(Value::Value)),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input>
where
'input: 'tape,
{
pub fn try_get_idx(&self, i: usize) -> Result<Option<Value<'_, 'tape, 'input>>, TryTypeError> {
match self {
Value::Tape(tape) => Ok(tape.try_get_idx(i)?.map(Value::Tape)),
Value::Value(value) => Ok(value.try_get_idx(i)?.map(Cow::Borrowed).map(Value::Value)),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input>
where
'input: 'tape,
{
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
pub fn as_array(&self) -> Option<Array<'_, 'tape, 'input>> {
match self {
Value::Tape(tape) => tape.as_array().map(Array::Tape),
Value::Value(value) => value.as_array().map(Array::Value),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
pub fn as_object(&self) -> Option<Object<'_, 'tape, 'input>> {
match self {
Value::Tape(tape) => tape.as_object().map(Object::Tape),
Value::Value(value) => value.as_object().map(Object::Value),
}
}
}
impl<'borrow, 'tape, 'input> ValueAsMutArray for Value<'borrow, 'tape, 'input> {
type Array = Vec<borrowed::Value<'input>>;
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_array_mut(&mut self) -> Option<&mut Vec<borrowed::Value<'input>>> {
self.as_mut().as_array_mut()
}
}
impl<'borrow, 'tape, 'input> ValueAsMutObject for Value<'borrow, 'tape, 'input> {
type Object = super::borrowed::Object<'input>;
#[cfg_attr(not(feature = "no-inline"), inline)]
#[must_use]
fn as_object_mut(&mut self) -> Option<&mut super::borrowed::Object<'input>> {
self.as_mut().as_object_mut()
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
pub fn try_as_array(&self) -> Result<Array<'_, 'tape, 'input>, TryTypeError> {
self.as_array().ok_or(TryTypeError {
expected: ValueType::Array,
got: self.value_type(),
})
}
pub fn try_as_object(&self) -> Result<Object<'_, 'tape, 'input>, TryTypeError> {
self.as_object().ok_or(TryTypeError {
expected: ValueType::Object,
got: self.value_type(),
})
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
#[must_use]
pub fn get<'k, Q>(&self, k: &'k Q) -> Option<Value<'_, 'tape, 'input>>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => tape.get(k).map(Value::Tape),
Value::Value(value) => value
.as_object()?
.get(k)
.map(Cow::Borrowed)
.map(Value::Value),
}
}
#[must_use]
pub fn contains_key<Q>(&self, k: &Q) -> bool
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
let Some(o) = self.as_object() else {
return false;
};
let v = o.get(k).is_some();
v
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
#[must_use]
pub fn get_idx(&self, i: usize) -> Option<Value<'_, 'tape, 'input>> {
match self {
Value::Tape(tape) => tape.get_idx(i).map(Value::Tape),
Value::Value(value) => value
.as_array()?
.get(i)
.map(Cow::Borrowed)
.map(Value::Value),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input>
where
'input: 'tape,
{
pub fn get_bool<Q>(&self, k: &Q) -> Option<bool>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_bool()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_i128<Q>(&self, k: &Q) -> Option<i128>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_i128()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_i64<Q>(&self, k: &Q) -> Option<i64>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_i64()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_i32<Q>(&self, k: &Q) -> Option<i32>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_i32()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_i16<Q>(&self, k: &Q) -> Option<i16>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_i16()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_i8<Q>(&self, k: &Q) -> Option<i8>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_i8()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_u128<Q>(&self, k: &Q) -> Option<u128>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k)?.as_u128()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_u64<Q>(&self, k: &Q) -> Option<u64>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_u64())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_usize<Q>(&self, k: &Q) -> Option<usize>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_usize())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_u32<Q>(&self, k: &Q) -> Option<u32>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_u32())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_u16<Q>(&self, k: &Q) -> Option<u16>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_u16())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_u8<Q>(&self, k: &Q) -> Option<u8>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_u8())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_f64<Q>(&self, k: &Q) -> Option<f64>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_f64())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_f32<Q>(&self, k: &Q) -> Option<f32>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.get(k).and_then(|v| v.as_f32())
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn get_str<Q>(&self, k: &Q) -> Option<&str>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => tape.get_str(k),
Value::Value(value) => value.get_str(k),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
#[must_use]
pub fn get_array<Q>(&self, k: &Q) -> Option<Array<'_, 'tape, 'input>>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => tape.get_array(k).map(Array::Tape),
Value::Value(value) => value.get_array(k).map(Array::Value),
}
}
#[must_use]
pub fn get_object<Q>(&self, k: &Q) -> Option<Object<'_, 'tape, 'input>>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => tape.get_object(k).map(Object::Tape),
Value::Value(value) => value.get_object(k).map(Object::Value),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
pub fn try_get_array<Q>(&self, k: &Q) -> Result<Option<Array<'_, 'tape, 'input>>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => Ok(tape.try_get_array(k)?.map(Array::Tape)),
Value::Value(value) => Ok(value.try_get_array(k)?.map(Array::Value)),
}
}
pub fn try_get_object<Q>(
&self,
k: &Q,
) -> Result<Option<Object<'_, 'tape, 'input>>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => Ok(tape.try_get_object(k)?.map(Object::Tape)),
Value::Value(value) => Ok(value.try_get_object(k)?.map(Object::Value)),
}
}
}
impl<'borrow, 'tape, 'input> Value<'borrow, 'tape, 'input> {
pub fn try_get_bool<Q>(&self, k: &Q) -> Result<Option<bool>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_bool()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_i128<Q>(&self, k: &Q) -> Result<Option<i128>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_i128()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_i64<Q>(&self, k: &Q) -> Result<Option<i64>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_i64()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_i32<Q>(&self, k: &Q) -> Result<Option<i32>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_i32()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_i16<Q>(&self, k: &Q) -> Result<Option<i16>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_i16()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_i8<Q>(&self, k: &Q) -> Result<Option<i8>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_i8()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_u128<Q>(&self, k: &Q) -> Result<Option<u128>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_u128()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_u64<Q>(&self, k: &Q) -> Result<Option<u64>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_u64()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_usize<Q>(&self, k: &Q) -> Result<Option<usize>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_usize()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_u32<Q>(&self, k: &Q) -> Result<Option<u32>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_u32()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_u16<Q>(&self, k: &Q) -> Result<Option<u16>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_u16()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_u8<Q>(&self, k: &Q) -> Result<Option<u8>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_u8()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_f64<Q>(&self, k: &Q) -> Result<Option<f64>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_f64()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_f32<Q>(&self, k: &Q) -> Result<Option<f32>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
self.try_get(k)?.map(|v| v.try_as_f32()).transpose()
}
#[cfg_attr(not(feature = "no-inline"), inline)]
pub fn try_get_str<Q>(&self, k: &Q) -> Result<Option<&'_ str>, TryTypeError>
where
str: Borrow<Q>,
for<'a> crate::cow::Cow<'a, str>: Borrow<Q>,
Q: ?Sized + Hash + Eq + Ord,
{
match self {
Value::Tape(tape) => tape.try_get_str(k),
Value::Value(value) => value.try_get_str(k),
}
}
}
impl<'borrow, 'tape, 'input> Writable for Value<'borrow, 'tape, 'input> {
#[cfg_attr(not(feature = "no-inline"), inline)]
fn encode(&self) -> String {
match self {
Value::Tape(tape) => tape.encode(),
Value::Value(value) => value.encode(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
fn encode_pp(&self) -> String {
match self {
Value::Tape(tape) => tape.encode_pp(),
Value::Value(value) => value.encode_pp(),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
fn write<'writer, W>(&self, w: &mut W) -> io::Result<()>
where
W: 'writer + Write,
{
match self {
Value::Tape(tape) => tape.write(w),
Value::Value(value) => value.write(w),
}
}
#[cfg_attr(not(feature = "no-inline"), inline)]
fn write_pp<'writer, W>(&self, w: &mut W) -> io::Result<()>
where
W: 'writer + Write,
{
match self {
Value::Tape(tape) => tape.write_pp(w),
Value::Value(value) => value.write_pp(w),
}
}
}