use std::borrow::Cow;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut, Range};
use std::sync::Arc;
use deser_core::ext::{BorrowedExtension, ExtValue, Extension, RawInput};
use deser_core::{Atom, Bytes, EventData, Implicit, ImplicitValue, Position};
use crate::index::ValueIndex;
use crate::map::Map;
use crate::seq::Seq;
use crate::tree;
pub struct Value {
pub(crate) kind: Kind,
pub(crate) meta: Option<Box<Meta>>,
}
#[non_exhaustive]
pub enum Kind {
Null,
Bool(bool),
U64(u64),
I64(i64),
F32(f32),
F64(f64),
Char(char),
Str(String),
Lexical(String),
Bytes(Bytes<'static>),
Ext(ExtValue<'static>),
Implicit(Implicit<'static>),
Seq(Seq),
Map(Map),
}
#[derive(Clone, Default, Debug)]
pub struct Meta {
event_data: EventData,
span: Option<Span>,
}
impl Meta {
pub fn new() -> Meta {
Meta::default()
}
pub fn event_data(&self) -> &EventData {
&self.event_data
}
pub fn event_data_mut(&mut self) -> &mut EventData {
&mut self.event_data
}
pub fn span(&self) -> Option<&Span> {
self.span.as_ref()
}
pub fn set_span(&mut self, span: Option<Span>) {
self.span = span;
}
pub fn is_empty(&self) -> bool {
self.event_data.is_empty() && self.span.is_none()
}
pub(crate) fn from_parts(event_data: EventData, span: Option<Span>) -> Meta {
Meta { event_data, span }
}
pub(crate) fn span_mut(&mut self) -> Option<&mut Span> {
self.span.as_mut()
}
}
#[derive(Clone)]
pub struct Span {
range: Range<usize>,
pub(crate) inner: Option<(usize, usize)>,
source: Arc<str>,
}
impl Span {
pub fn new(range: Range<usize>, source: Arc<str>) -> Span {
Span {
range,
inner: None,
source,
}
}
pub fn range(&self) -> Range<usize> {
self.range.clone()
}
pub fn source(&self) -> &Arc<str> {
&self.source
}
pub fn text(&self) -> Option<&str> {
self.source.get(self.range.clone())
}
pub fn start(&self) -> Position {
Position::of(self.source.as_bytes(), self.range.start)
}
pub fn end(&self) -> Position {
Position::of(self.source.as_bytes(), self.range.end)
}
pub(crate) fn start_range(&self) -> (usize, usize) {
match self.inner {
Some((start_end, _)) => (self.range.start, start_end),
None => (self.range.start, self.range.end),
}
}
pub(crate) fn end_range(&self) -> Option<(usize, usize)> {
self.inner.map(|(_, end_start)| (end_start, self.range.end))
}
pub(crate) fn set_end(&mut self, end_start: usize, end: usize) {
self.inner = Some((self.range.end, end_start));
self.range.end = end;
}
}
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Span")
.field("range", &self.range)
.finish_non_exhaustive()
}
}
static NULL: Value = Value::null();
impl Value {
pub const fn null() -> Value {
Value {
kind: Kind::Null,
meta: None,
}
}
pub const fn new(kind: Kind) -> Value {
Value { kind, meta: None }
}
pub fn ext<T: Extension>(value: T) -> Value {
Value::from(ExtValue::owned(value))
}
pub fn bytes<B: Into<Vec<u8>>>(data: B) -> Value {
Value::new(Kind::Bytes(Bytes::new(data.into())))
}
pub fn kind(&self) -> &Kind {
&self.kind
}
pub fn kind_mut(&mut self) -> &mut Kind {
&mut self.kind
}
pub fn into_kind(self) -> Kind {
self.kind
}
pub fn into_parts(self) -> (Kind, Option<Meta>) {
(self.kind, self.meta.map(|meta| *meta))
}
pub fn meta(&self) -> Option<&Meta> {
self.meta.as_deref()
}
pub fn meta_mut(&mut self) -> &mut Meta {
self.meta.get_or_insert_with(Default::default)
}
pub fn take_meta(&mut self) -> Option<Meta> {
self.meta.take().map(|meta| *meta)
}
pub fn set_meta(&mut self, meta: Option<Meta>) {
self.meta = meta.filter(|meta| !meta.is_empty()).map(Box::new);
}
pub fn span(&self) -> Option<&Span> {
self.meta().and_then(Meta::span)
}
pub fn event_data(&self) -> Option<&EventData> {
self.meta().map(Meta::event_data)
}
pub fn take(&mut self) -> Value {
std::mem::take(self)
}
}
impl Default for Value {
fn default() -> Value {
Value::null()
}
}
impl Deref for Value {
type Target = Kind;
fn deref(&self) -> &Kind {
&self.kind
}
}
impl DerefMut for Value {
fn deref_mut(&mut self) -> &mut Kind {
&mut self.kind
}
}
impl Clone for Value {
fn clone(&self) -> Value {
Value {
kind: self.kind.clone(),
meta: self.meta.clone(),
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
tree::eq_kind(&self.kind, &other.kind)
}
}
impl Eq for Value {}
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
tree::hash_kind(&self.kind, state);
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
tree::fmt_kind(&self.kind, f)
}
}
impl<I: ValueIndex> std::ops::Index<I> for Value {
type Output = Value;
fn index(&self, index: I) -> &Value {
index.index_into(&self.kind).unwrap_or(&NULL)
}
}
impl<I: ValueIndex> std::ops::IndexMut<I> for Value {
fn index_mut(&mut self, index: I) -> &mut Value {
index.index_or_insert(self)
}
}
impl Kind {
pub fn name(&self) -> &str {
match self {
Kind::Null => "null",
Kind::Bool(_) => "bool",
Kind::U64(_) => "unsigned integer",
Kind::I64(_) => "signed integer",
Kind::F32(_) | Kind::F64(_) => "float",
Kind::Char(_) => "char",
Kind::Str(_) | Kind::Lexical(_) => "string",
Kind::Bytes(_) => "bytes",
Kind::Ext(ext) => ext.name(),
Kind::Implicit(value) => value.value().name(),
Kind::Seq(_) => "sequence",
Kind::Map(_) => "map",
}
}
pub fn is_null(&self) -> bool {
match self {
Kind::Null => true,
Kind::Ext(ext) => matches!(ext.fallback(), Atom::Null),
Kind::Implicit(value) => value.value() == ImplicitValue::Null,
_ => false,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Kind::Bool(value) => Some(*value),
Kind::Ext(ext) => match ext.fallback() {
Atom::Bool(value) => Some(value),
_ => None,
},
Kind::Implicit(value) => Kind::from_implicit(value.value()).as_bool(),
_ => None,
}
}
pub fn as_u64(&self) -> Option<u64> {
self.as_i128().and_then(|value| u64::try_from(value).ok())
}
pub fn as_i64(&self) -> Option<i64> {
self.as_i128().and_then(|value| i64::try_from(value).ok())
}
pub fn as_u128(&self) -> Option<u128> {
match self {
Kind::Ext(ext) if ext.is::<u128>() => ext.downcast_ref::<u128>().copied(),
_ => self.as_i128().and_then(|value| u128::try_from(value).ok()),
}
}
pub fn as_i128(&self) -> Option<i128> {
match self {
Kind::U64(value) => Some(i128::from(*value)),
Kind::I64(value) => Some(i128::from(*value)),
Kind::Implicit(value) => Kind::from_implicit(value.value()).as_i128(),
Kind::Ext(ext) => {
if let Some(value) = ext.downcast_ref::<i128>() {
Some(*value)
} else if let Some(value) = ext.downcast_ref::<u128>() {
i128::try_from(*value).ok()
} else {
match ext.fallback() {
Atom::U64(value) => Some(i128::from(value)),
Atom::I64(value) => Some(i128::from(value)),
_ => None,
}
}
}
_ => None,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self {
Kind::F64(value) => Some(*value),
Kind::F32(value) => Some(f64::from(*value)),
Kind::U64(value) => Some(*value as f64),
Kind::I64(value) => Some(*value as f64),
Kind::Implicit(value) => Kind::from_implicit(value.value()).as_f64(),
Kind::Ext(ext) => match ext.fallback() {
Atom::F64(value) => Some(value),
Atom::F32(value) => Some(f64::from(value)),
Atom::U64(value) => Some(value as f64),
Atom::I64(value) => Some(value as f64),
_ => None,
},
_ => None,
}
}
pub fn as_char(&self) -> Option<char> {
match self {
Kind::Char(value) => Some(*value),
_ => None,
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Kind::Str(value) | Kind::Lexical(value) => Some(value),
Kind::Ext(ext) => match ext.fallback() {
Atom::Str(value) => value.borrowed_str(),
_ => None,
},
_ => None,
}
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
Kind::Bytes(value) => Some(value.data()),
_ => None,
}
}
pub fn as_seq(&self) -> Option<&Seq> {
match self {
Kind::Seq(value) => Some(value),
_ => None,
}
}
pub fn as_seq_mut(&mut self) -> Option<&mut Seq> {
match self {
Kind::Seq(value) => Some(value),
_ => None,
}
}
pub fn as_map(&self) -> Option<&Map> {
match self {
Kind::Map(value) => Some(value),
_ => None,
}
}
pub fn as_map_mut(&mut self) -> Option<&mut Map> {
match self {
Kind::Map(value) => Some(value),
_ => None,
}
}
pub fn as_ext(&self) -> Option<&ExtValue<'static>> {
match self {
Kind::Ext(value) => Some(value),
_ => None,
}
}
pub fn downcast_ext<T: Extension>(&self) -> Option<&T> {
self.as_ext().and_then(|ext| ext.downcast_ref::<T>())
}
pub fn downcast_ext_value<K: BorrowedExtension>(&self) -> Option<&K::Value<'_>> {
self.as_ext().and_then(|ext| ext.downcast_value_ref::<K>())
}
pub fn is_str(&self) -> bool {
matches!(self, Kind::Str(_) | Kind::Lexical(_))
}
pub fn is_lexical(&self) -> bool {
matches!(self, Kind::Lexical(_))
}
pub fn is_seq(&self) -> bool {
matches!(self, Kind::Seq(_))
}
pub fn is_map(&self) -> bool {
matches!(self, Kind::Map(_))
}
pub fn get<I: ValueIndex>(&self, index: I) -> Option<&Value> {
index.index_into(self)
}
pub fn get_mut<I: ValueIndex>(&mut self, index: I) -> Option<&mut Value> {
index.index_into_mut(self)
}
#[inline]
pub(crate) fn has_children(&self) -> bool {
match self {
Kind::Seq(seq) => !seq.is_empty(),
Kind::Map(map) => !map.is_empty(),
_ => false,
}
}
}
impl Clone for Kind {
fn clone(&self) -> Kind {
tree::clone_kind(self)
}
}
impl PartialEq for Kind {
fn eq(&self, other: &Kind) -> bool {
tree::eq_kind(self, other)
}
}
impl Eq for Kind {}
impl Hash for Kind {
fn hash<H: Hasher>(&self, state: &mut H) {
tree::hash_kind(self, state);
}
}
impl fmt::Debug for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
tree::fmt_kind(self, f)
}
}
impl From<Kind> for Value {
fn from(kind: Kind) -> Value {
Value::new(kind)
}
}
impl From<()> for Value {
fn from(_: ()) -> Value {
Value::null()
}
}
impl From<bool> for Value {
fn from(value: bool) -> Value {
Value::new(Kind::Bool(value))
}
}
impl From<char> for Value {
fn from(value: char) -> Value {
Value::new(Kind::Char(value))
}
}
macro_rules! from_unsigned {
($($ty:ty),*) => {
$(
impl From<$ty> for Value {
fn from(value: $ty) -> Value {
Value::new(Kind::U64(value as u64))
}
}
)*
};
}
macro_rules! from_signed {
($($ty:ty),*) => {
$(
impl From<$ty> for Value {
fn from(value: $ty) -> Value {
Value::new(Kind::from_i64(value as i64))
}
}
)*
};
}
from_unsigned!(u8, u16, u32, u64, usize);
from_signed!(i8, i16, i32, i64, isize);
impl Kind {
pub(crate) fn from_i64(value: i64) -> Kind {
match u64::try_from(value) {
Ok(value) => Kind::U64(value),
Err(_) => Kind::I64(value),
}
}
pub(crate) fn from_implicit(value: ImplicitValue) -> Kind {
match value {
ImplicitValue::Null => Kind::Null,
ImplicitValue::Bool(value) => Kind::Bool(value),
ImplicitValue::U64(value) => Kind::U64(value),
ImplicitValue::I64(value) => Kind::from_i64(value),
ImplicitValue::F64(value) => Kind::F64(value),
_ => Kind::Null,
}
}
pub(crate) fn from_ext(ext: ExtValue<'_>) -> Kind {
if let Some(input) = ext.downcast_value_ref::<RawInput>() {
if let Ok(value) = input.deserialize::<Value>() {
return value.kind;
}
} else if let Some(&value) = ext.downcast_ref::<u128>() {
if let Ok(value) = u64::try_from(value) {
return Kind::U64(value);
}
} else if let Some(&value) = ext.downcast_ref::<i128>()
&& let Ok(value) = i64::try_from(value)
{
return Kind::from_i64(value);
}
Kind::Ext(ext.to_static())
}
}
impl From<u128> for Value {
fn from(value: u128) -> Value {
Value::new(match u64::try_from(value) {
Ok(value) => Kind::U64(value),
Err(_) => Kind::Ext(ExtValue::owned(value)),
})
}
}
impl From<i128> for Value {
fn from(value: i128) -> Value {
Value::new(match i64::try_from(value) {
Ok(value) => Kind::from_i64(value),
Err(_) => Kind::Ext(ExtValue::owned(value)),
})
}
}
impl From<f32> for Value {
fn from(value: f32) -> Value {
Value::new(Kind::F32(value))
}
}
impl From<f64> for Value {
fn from(value: f64) -> Value {
Value::new(Kind::F64(value))
}
}
impl From<&str> for Value {
fn from(value: &str) -> Value {
Value::new(Kind::Str(value.to_string()))
}
}
impl From<String> for Value {
fn from(value: String) -> Value {
Value::new(Kind::Str(value))
}
}
impl From<&String> for Value {
fn from(value: &String) -> Value {
Value::new(Kind::Str(value.clone()))
}
}
impl From<Cow<'_, str>> for Value {
fn from(value: Cow<'_, str>) -> Value {
Value::new(Kind::Str(value.into_owned()))
}
}
impl From<Bytes<'_>> for Value {
fn from(value: Bytes<'_>) -> Value {
Value::new(Kind::Bytes(owned_bytes(value)))
}
}
impl From<ExtValue<'_>> for Value {
fn from(value: ExtValue<'_>) -> Value {
Value::new(Kind::from_ext(value))
}
}
impl From<Seq> for Value {
fn from(value: Seq) -> Value {
Value::new(Kind::Seq(value))
}
}
impl From<Map> for Value {
fn from(value: Map) -> Value {
Value::new(Kind::Map(value))
}
}
impl<T: Into<Value>> From<Option<T>> for Value {
fn from(value: Option<T>) -> Value {
match value {
Some(value) => value.into(),
None => Value::null(),
}
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
fn from(value: Vec<T>) -> Value {
Value::from(value.into_iter().collect::<Seq>())
}
}
impl<T: Clone + Into<Value>> From<&[T]> for Value {
fn from(value: &[T]) -> Value {
Value::from(value.iter().cloned().collect::<Seq>())
}
}
impl<T: Into<Value>> FromIterator<T> for Value {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Value {
Value::from(iter.into_iter().collect::<Seq>())
}
}
impl<K: Into<Value>, V: Into<Value>> FromIterator<(K, V)> for Value {
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Value {
Value::from(iter.into_iter().collect::<Map>())
}
}
pub(crate) fn owned_bytes(bytes: Bytes<'_>) -> Bytes<'static> {
let fallback = bytes.fallback;
let mut owned = Bytes::new(bytes.into_owned());
owned.fallback = fallback;
owned
}
impl PartialEq<str> for Value {
fn eq(&self, other: &str) -> bool {
matches!(self.kind, Kind::Str(ref value) | Kind::Lexical(ref value) if value == other)
}
}
impl PartialEq<&str> for Value {
fn eq(&self, other: &&str) -> bool {
*self == **other
}
}
impl PartialEq<String> for Value {
fn eq(&self, other: &String) -> bool {
*self == **other
}
}
impl PartialEq<bool> for Value {
fn eq(&self, other: &bool) -> bool {
matches!(self.kind, Kind::Bool(value) if value == *other)
}
}
impl PartialEq<f64> for Value {
fn eq(&self, other: &f64) -> bool {
match self.kind {
Kind::F64(value) => value == *other,
Kind::F32(value) => f64::from(value) == *other,
_ => false,
}
}
}
impl PartialEq<f32> for Value {
fn eq(&self, other: &f32) -> bool {
*self == f64::from(*other)
}
}
macro_rules! eq_int {
($($ty:ty),*) => {
$(
impl PartialEq<$ty> for Value {
fn eq(&self, other: &$ty) -> bool {
match self.kind {
Kind::U64(value) => i128::from(value) == *other as i128,
Kind::I64(value) => i128::from(value) == *other as i128,
_ => false,
}
}
}
)*
};
}
eq_int!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);