mod de;
mod debug;
mod from;
mod index;
mod partial_eq;
mod ser;
pub(crate) mod tagged;
use crate::error::{self, Error, ErrorImpl};
use crate::{spanned, Span};
use serde::de::{Deserialize, DeserializeOwned, IntoDeserializer};
use serde::Serialize;
use std::hash::{Hash, Hasher};
use std::mem;
pub use self::index::Index;
pub use self::ser::Serializer;
pub use self::tagged::{Tag, TaggedValue};
#[doc(inline)]
pub use crate::mapping::Mapping;
pub use crate::number::Number;
#[doc(inline)]
pub(crate) use de::ValueVisitor;
pub use de::extract_reusable_deserializer_state;
pub use de::extract_tag_and_deserializer_state;
pub use de::DeserializerState;
pub use de::DuplicateKeyCallback;
pub use de::FieldTransformer;
pub use de::TransformedResult;
pub use de::UnusedKeyCallback;
#[derive(Clone)]
pub enum Value {
Null(Span),
Bool(bool, Span),
Number(Number, Span),
String(String, Span),
Sequence(Sequence, Span),
Mapping(Mapping, Span),
Tagged(Box<TaggedValue>, Span),
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
match (self, other) {
(Value::Null(..), Value::Null(..)) => true,
(Value::Bool(a, ..), Value::Bool(b, ..)) => a == b,
(Value::Number(a, ..), Value::Number(b, ..)) => a == b,
(Value::String(a, ..), Value::String(b, ..)) => a == b,
(Value::Sequence(a, ..), Value::Sequence(b, ..)) => a == b,
(Value::Mapping(a, ..), Value::Mapping(b, ..)) => a == b,
(Value::Tagged(a, ..), Value::Tagged(b, ..)) => a == b,
_ => false,
}
}
}
impl PartialOrd for Value {
fn partial_cmp(&self, other: &Value) -> Option<std::cmp::Ordering> {
match (self, other) {
(Value::Null(..), Value::Null(..)) => Some(std::cmp::Ordering::Equal),
(Value::Bool(a, ..), Value::Bool(b, ..)) => a.partial_cmp(b),
(Value::Number(a, ..), Value::Number(b, ..)) => a.partial_cmp(b),
(Value::String(a, ..), Value::String(b, ..)) => a.partial_cmp(b),
(Value::Sequence(a, ..), Value::Sequence(b, ..)) => a.partial_cmp(b),
(Value::Mapping(a, ..), Value::Mapping(b, ..)) => a.partial_cmp(b),
(Value::Tagged(a, ..), Value::Tagged(b, ..)) => a.partial_cmp(b),
_ => None,
}
}
}
impl Default for Value {
fn default() -> Value {
Value::Null(Span::default())
}
}
pub type Sequence = Vec<Value>;
pub fn to_value<T>(value: T) -> Result<Value, Error>
where
T: Serialize,
{
value.serialize(Serializer)
}
pub fn from_value<T>(value: Value) -> Result<T, Error>
where
T: DeserializeOwned,
{
value.broadcast_start_mark();
let res = Deserialize::deserialize(value.into_deserializer());
spanned::reset_marker();
res
}
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_null(&self) -> bool {
if let Value::Null(..) = self.untag_ref() {
true
} else {
false
}
}
pub fn as_null(&self) -> Option<()> {
match self.untag_ref() {
Value::Null(..) => Some(()),
_ => None,
}
}
pub fn is_bool(&self) -> bool {
self.as_bool().is_some()
}
pub fn as_bool(&self) -> Option<bool> {
match self.untag_ref() {
Value::Bool(b, ..) => Some(*b),
_ => None,
}
}
pub fn is_number(&self) -> bool {
match self.untag_ref() {
Value::Number(..) => true,
_ => false,
}
}
pub fn is_i64(&self) -> bool {
self.as_i64().is_some()
}
pub fn as_i64(&self) -> Option<i64> {
match self.untag_ref() {
Value::Number(n, ..) => n.as_i64(),
_ => None,
}
}
pub fn is_u64(&self) -> bool {
self.as_u64().is_some()
}
pub fn as_u64(&self) -> Option<u64> {
match self.untag_ref() {
Value::Number(n, ..) => n.as_u64(),
_ => None,
}
}
pub fn is_f64(&self) -> bool {
match self.untag_ref() {
Value::Number(n, ..) => n.is_f64(),
_ => false,
}
}
pub fn as_f64(&self) -> Option<f64> {
match self.untag_ref() {
Value::Number(i, ..) => i.as_f64(),
_ => None,
}
}
pub fn is_string(&self) -> bool {
self.as_str().is_some()
}
pub fn as_str(&self) -> Option<&str> {
match self.untag_ref() {
Value::String(s, ..) => Some(s),
_ => None,
}
}
pub fn is_sequence(&self) -> bool {
self.as_sequence().is_some()
}
pub fn as_sequence(&self) -> Option<&Sequence> {
match self.untag_ref() {
Value::Sequence(seq, ..) => Some(seq),
_ => None,
}
}
pub fn as_sequence_mut(&mut self) -> Option<&mut Sequence> {
match self.untag_mut() {
Value::Sequence(seq, ..) => Some(seq),
_ => None,
}
}
pub fn is_mapping(&self) -> bool {
self.as_mapping().is_some()
}
pub fn as_mapping(&self) -> Option<&Mapping> {
match self.untag_ref() {
Value::Mapping(map, ..) => Some(map),
_ => None,
}
}
pub fn as_mapping_mut(&mut self) -> Option<&mut Mapping> {
match self.untag_mut() {
Value::Mapping(map, ..) => Some(map),
_ => None,
}
}
pub fn apply_merge(&mut self) -> Result<(), Error> {
let mut stack = Vec::new();
stack.push(self);
while let Some(node) = stack.pop() {
match node {
Value::Mapping(mapping, ..) => {
loop {
match mapping.remove("<<") {
Some(Value::Mapping(merge, ..)) => {
for (k, v) in merge {
mapping.entry(k).or_insert(v);
}
}
Some(Value::Sequence(sequence, ..)) => {
for value in sequence {
match value {
Value::Mapping(merge, ..) => {
for (k, v) in merge {
mapping.entry(k).or_insert(v);
}
}
Value::Sequence(..) => {
return Err(error::new(
ErrorImpl::SequenceInMergeElement,
));
}
Value::Tagged(..) => {
return Err(error::new(ErrorImpl::TaggedInMerge));
}
_unexpected => {
return Err(error::new(
ErrorImpl::ScalarInMergeElement,
));
}
}
}
}
None => {
break;
}
Some(Value::Tagged(..)) => {
return Err(error::new(ErrorImpl::TaggedInMerge))
}
Some(_unexpected) => return Err(error::new(ErrorImpl::ScalarInMerge)),
}
}
stack.extend(mapping.values_mut());
}
Value::Sequence(sequence, ..) => stack.extend(sequence),
Value::Tagged(tagged, ..) => stack.push(&mut tagged.value),
_ => {}
}
}
Ok(())
}
pub fn span(&self) -> &Span {
match self {
Value::Null(span)
| Value::Bool(_, span)
| Value::Number(_, span)
| Value::Sequence(_, span)
| Value::Mapping(_, span)
| Value::Tagged(_, span)
| Value::String(_, span) => span,
}
}
pub fn with_span(self, span: impl Into<Span>) -> Self {
let mut this = self;
let span = span.into();
this.set_span(span);
this
}
fn set_span(&mut self, span: Span) {
match self {
Value::Null(ref mut s)
| Value::Bool(_, ref mut s)
| Value::Number(_, ref mut s)
| Value::Sequence(_, ref mut s)
| Value::Mapping(_, ref mut s)
| Value::Tagged(_, ref mut s)
| Value::String(_, ref mut s) => *s = span,
}
}
fn broadcast_start_mark(&self) {
spanned::set_marker(self.span().start);
#[cfg(feature = "filename")]
if let Some(filename) = &self.span().filename {
spanned::set_filename(std::sync::Arc::clone(filename));
}
}
fn broadcast_end_mark(&self) {
spanned::set_marker(self.span().end);
#[cfg(feature = "filename")]
if let Some(filename) = &self.span().filename {
spanned::set_filename(std::sync::Arc::clone(filename));
}
}
}
impl Value {
pub const fn null() -> Value {
Value::Null(Span::zero())
}
pub const fn bool(b: bool) -> Value {
Value::Bool(b, Span::zero())
}
pub const fn number(n: Number) -> Value {
Value::Number(n, Span::zero())
}
pub const fn string(s: String) -> Value {
Value::String(s, Span::zero())
}
pub fn sequence(seq: Sequence) -> Value {
Value::Sequence(seq, Span::zero())
}
pub fn mapping(map: Mapping) -> Value {
Value::Mapping(map, Span::zero())
}
pub fn tagged(tagged: impl Into<Box<TaggedValue>>) -> Value {
Value::Tagged(tagged.into(), Span::zero())
}
}
impl Eq for Value {}
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
mem::discriminant(self).hash(state);
match self {
Value::Null(..) => {}
Value::Bool(v, ..) => v.hash(state),
Value::Number(v, ..) => v.hash(state),
Value::String(v, ..) => v.hash(state),
Value::Sequence(v, ..) => v.hash(state),
Value::Mapping(v, ..) => v.hash(state),
Value::Tagged(v, ..) => v.hash(state),
}
}
}
impl IntoDeserializer<'_, Error> for Value {
type Deserializer = de::ValueDeserializer<'static, 'static, 'static>;
fn into_deserializer(self) -> Self::Deserializer {
de::ValueDeserializer::new(self)
}
}
#[cfg(feature = "schemars")]
impl schemars::JsonSchema for Value {
fn schema_name() -> String {
"AnyValue".into()
}
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::schema::Schema {
true.into()
}
}