macro_rules! define_yaml_scalar_conversion_ops (
(owned) => (
define_yaml_scalar_conversion_ops!(base);
define_as_ref_mut!(as_string_mut, &mut String, String);
define_as_ref_mut!(as_str_mut, &mut str, String);
);
(borrowing) => (
define_yaml_scalar_conversion_ops!(base);
define_as_ref!(as_cow, &Cow<'input, str>, String);
define_as_ref_mut!(as_cow_mut, &mut Cow<'input, str>, String);
define_into!(into_cow, Cow<'input, str>, String);
define_as_ref_mut_pattern!(as_str_mut, &mut str => Self::String(ref mut v) => Some(v.to_mut()));
);
(base) => ( define_as!(as_bool, bool, Boolean);
define_as!(as_integer, i64, Integer);
define_as!(as_floating_point, f64, FloatingPoint);
define_as_ref!(as_str, &str, String);
define_as_ref_mut!(as_bool_mut, &mut bool, Boolean);
define_as_ref_mut!(as_integer_mut, &mut i64, Integer);
define_as_ref_mut!(as_floating_point_mut, &mut f64, FloatingPoint);
define_into!(into_boolean, bool, Boolean);
define_into!(into_i64, i64, Integer);
define_into!(into_f64, f64, FloatingPoint);
define_into!(into_string, String, String);
define_is!(is_null, Self::Null);
define_is!(is_boolean, Self::Boolean(_));
define_is!(is_integer, Self::Integer(_));
define_is!(is_floating_point, Self::FloatingPoint(_));
define_is!(is_string, Self::String(_));
);
);
macro_rules! define_yaml_object_impl (
(
$yaml:ty,
$( < $( $generic:tt ),+ >, )?
$( where { $($whereclause:tt)+ }, )?
mappingtype = $mappingtype:ty,
sequencetype = $sequencetype:ty,
nodetype = $nodetype:ty,
scalartype = { $scalartype:tt },
selfname = $selfname:literal,
owned
) => (
define_yaml_object_impl!(
$yaml,
$( < $($generic),+>, )?
$(where { $($whereclause)+ }, )?
mappingtype = $mappingtype,
sequencetype = $sequencetype,
nodetype = $nodetype,
scalartype = { $scalartype },
selfname = $selfname,
base
);
impl $(< $( $generic ),+ >)? $yaml $(where $($whereclause)+)? {
define_as_ref_mut_pattern!(as_str_mut, &mut str => Self::Value($scalartype::String(ref mut v)) => Some(v.as_mut()));
pub fn parse_representation(&mut self) -> bool {
match self.take() {
Self::Representation(value, style, tag) => {
if let Some(scalar) =
$scalartype::parse_from_cow_and_metadata(value.into(), style, tag.map(std::borrow::Cow::Owned).as_ref())
{
*self = Self::Value(scalar);
true
} else {
*self = Self::BadValue;
false
}
}
_ => true,
}
}
#[must_use]
pub fn get_tag(&self) -> Option<&Tag> {
match self {
Self::Tagged(tag, _) => Some(&tag),
Self::Representation(_, _, tag) => tag.as_ref(),
_ => None
}
}
}
);
(
$yaml:ty,
< $( $generic:tt ),+ >,
$( where { $($whereclause:tt)+ }, )?
mappingtype = $mappingtype:ty,
sequencetype = $sequencetype:ty,
nodetype = $nodetype:ty,
scalartype = { $scalartype:tt },
selfname = $selfname:literal,
borrowing
) => (
define_yaml_object_impl!(
$yaml,
< $($generic),+>,
$(where { $($whereclause)+ }, )?
mappingtype = $mappingtype,
sequencetype = $sequencetype,
nodetype = $nodetype,
scalartype = { $scalartype },
selfname = $selfname,
base
);
impl< $( $generic ),+ > $yaml $(where $($whereclause)+)? {
define_as_ref_pattern!(as_cow, &Cow<'input, str> => Self::Value($scalartype::String(ref v)) => Some(v));
define_as_ref_mut_pattern!(as_cow_mut, &mut Cow<'input, str> => Self::Value($scalartype::String(ref mut v)) => Some(v));
define_into_pattern!(into_cow, Cow<'input, str> => Self::Value($scalartype::String(v)) => Some(v));
define_as_ref_mut_pattern!(as_str_mut, &mut str => Self::Value($scalartype::String(ref mut v)) => Some(v.to_mut()));
pub fn parse_representation(&mut self) -> bool {
match self.take() {
Self::Representation(value, style, tag) => {
if let Some(scalar) =
$scalartype::parse_from_cow_and_metadata(value.into(), style, tag.as_ref())
{
*self = Self::Value(scalar);
true
} else {
*self = Self::BadValue;
false
}
}
_ => true,
}
}
#[must_use]
pub fn value_from_str(v: &'input str) -> Self {
Self::value_from_cow(v.into())
}
#[must_use]
pub fn scalar_from_string(v: String) -> Self {
Self::value_from_cow(v.into())
}
#[must_use]
pub fn value_from_cow(v: Cow<'input, str>) -> Self {
Self::Value(Scalar::parse_from_cow(v))
}
#[must_use]
pub fn value_from_cow_and_metadata(
v: Cow<'input, str>,
style: ScalarStyle,
tag: Option<&Cow<'input, Tag>>,
) -> Self {
match tag {
Some(tag) if !tag.is_yaml_core_schema() => {
Self::Tagged(tag.clone(), Box::new(Self::value_from_cow_and_metadata(v, style, None).into()))
}
_ => Scalar::parse_from_cow_and_metadata(v, style, tag).map_or(Self::BadValue, Self::Value)
}
}
#[must_use]
pub fn get_tag(&self) -> Option<&Tag> {
use std::borrow::Borrow;
match self {
Self::Tagged(tag, _) => Some(tag.borrow()),
Self::Representation(_, _, tag) => tag.as_ref().map(Borrow::borrow),
_ => None
}
}
}
);
(
$yaml:ty,
$( < $( $generic:tt ),+ >, )?
$( where { $($whereclause:tt)+ }, )?
mappingtype = $mappingtype:ty,
sequencetype = $sequencetype:ty,
nodetype = $nodetype:ty,
scalartype = { $scalartype:tt },
selfname = $selfname:literal,
base
) => (
impl $(< $( $generic ),+ >)? $yaml $(where $($whereclause)+)? {
define_as_pattern!(as_bool, bool => Self::Value($scalartype::Boolean(v)) => Some(v.into()));
define_as_pattern!(as_integer, i64 => Self::Value($scalartype::Integer(v)) => Some(v.into()));
define_as_pattern!(as_floating_point, f64 => Self::Value($scalartype::FloatingPoint(v)) => Some(v.into()));
define_as_ref_pattern!(as_str, &str => Self::Value($scalartype::String(v)) => Some(v));
define_as_ref_mut_pattern!(as_bool_mut, &mut bool => Self::Value($scalartype::Boolean(ref mut v)) => Some(v));
define_as_ref_mut_pattern!(as_integer_mut, &mut i64 => Self::Value($scalartype::Integer(ref mut v)) => Some(v));
define_as_ref_mut_pattern!(as_floating_point_mut, &mut f64 => Self::Value($scalartype::FloatingPoint(ref mut v)) => Some(v));
define_into_pattern!(into_bool, bool => Self::Value($scalartype::Boolean(v)) => Some(v));
define_into_pattern!(into_integer, i64 => Self::Value($scalartype::Integer(v)) => Some(v));
define_into_pattern!(into_floating_point, f64 => Self::Value($scalartype::FloatingPoint(v)) => Some(v.into()));
define_into_pattern!(into_string, String => Self::Value($scalartype::String(v)) => Some(v.into()));
define_as_ref!(as_mapping, &$mappingtype, Mapping);
define_as_ref!(as_sequence, &$sequencetype, Sequence);
define_as_ref!(as_vec, &$sequencetype, Sequence);
define_as_ref_mut!(as_mapping_mut, &mut $mappingtype, Mapping);
define_as_ref_mut!(as_sequence_mut, &mut $sequencetype, Sequence);
define_as_ref_mut!(as_vec_mut, &mut $sequencetype, Sequence);
define_into!(into_mapping, $mappingtype, Mapping);
define_into!(into_vec, $sequencetype, Sequence);
define_into!(into_sequence, $sequencetype, Sequence);
define_is!(is_boolean, Self::Value($scalartype::Boolean(_)));
define_is!(is_integer, Self::Value($scalartype::Integer(_)));
define_is!(is_null, Self::Value($scalartype::Null));
define_is!(is_floating_point, Self::Value($scalartype::FloatingPoint(_)));
define_is!(is_string, Self::Value($scalartype::String(_)));
define_is!(is_sequence, Self::Sequence(_));
define_is!(is_badvalue, Self::BadValue);
define_is!(is_mapping, Self::Mapping(_));
define_is!(is_alias, Self::Alias(_));
define_is!(is_representation, Self::Representation(..));
define_is!(is_value, Self::Value(_));
define_is!(is_tag_node, Self::Tagged(..));
#[must_use]
pub fn get_tagged_node(&self) -> Option<&$nodetype> {
if let Self::Tagged(_, node) = self {
Some(node.as_ref())
} else {
None
}
}
#[must_use]
pub fn get_tagged_node_mut(&mut self) -> Option<&mut $nodetype> {
if let Self::Tagged(_, node) = self {
Some(node.as_mut())
} else {
None
}
}
#[must_use]
pub fn is_empty_collection(&self) -> bool {
matches!(self, Self::Sequence(x) if x.is_empty()) ||
matches!(self, Self::Mapping(x) if x.is_empty())
}
#[must_use]
pub fn is_non_empty_collection(&self) -> bool {
matches!(self, Self::Sequence(x) if !x.is_empty()) ||
matches!(self, Self::Mapping(x) if !x.is_empty())
}
#[allow(clippy::unnecessary_fold)]
pub fn parse_representation_recursive(&mut self) -> bool {
match self.take() {
mut zelf @ Self::Representation(..) => {
let succeeded = zelf.parse_representation();
*self = zelf;
succeeded
}
Self::Sequence(mut vec) => vec
.iter_mut()
.map(|v| v.parse_representation_recursive())
.fold(true, |a, b| a && b),
Self::Mapping(mut map) => {
let mut succeeded = true;
let mut tmp = LinkedHashMap::default();
std::mem::swap(&mut tmp, &mut map);
map = tmp
.into_iter()
.map(|(mut k, mut v)| {
let a = k.parse_representation_recursive();
let b = v.parse_representation_recursive();
succeeded = succeeded && a && b;
(k, v)
})
.collect::<LinkedHashMap<_, _, _>>();
*self = Self::Mapping(map);
succeeded
}
_ => true,
}
}
#[must_use]
pub fn or(self, other: Self) -> Self {
match self {
Self::BadValue | Self::Value($scalartype::Null) => other,
this => this,
}
}
#[must_use]
pub fn borrowed_or<'a>(&'a self, other: &'a Self) -> &'a Self {
match self {
Self::BadValue | Self::Value($scalartype::Null) => other,
this => this,
}
}
#[must_use]
pub fn contains_mapping_key(&self, key: &str) -> bool {
self.as_mapping_get_impl(key).is_some()
}
#[must_use]
pub fn as_mapping_get(&self, key: &str) -> Option<&$nodetype> {
self.as_mapping_get_impl(key)
}
#[must_use]
pub fn as_mapping_get_mut(&mut self, key: &str) -> Option<&mut $nodetype> {
self.as_mapping_get_mut_impl(key)
}
#[must_use]
pub fn as_sequence_get(&self, idx:usize) -> Option<&$nodetype> {
self.as_sequence().and_then(|seq| seq.get(idx))
}
#[must_use]
pub fn as_sequence_get_mut(&mut self, idx:usize) -> Option<&mut $nodetype> {
self.as_sequence_mut().and_then(|seq| seq.get_mut(idx))
}
}
define_yaml_object_index_traits_impl!(
$yaml,
$(< $( $generic ),+ >,)?
$( where { $($whereclause)+ }, )?
mappingtype = $mappingtype,
sequencetype = $sequencetype,
nodetype = $nodetype,
scalartype = { $scalartype },
selfname = $selfname
);
);
);
macro_rules! define_yaml_object_index_traits_impl (
(
$yaml:ty,
$(< $( $generic:tt ),+ >,)?
$( where { $($whereclause:tt)+ }, )?
mappingtype = $mappingtype:ty,
sequencetype = $sequencetype:ty,
nodetype = $nodetype:ty,
scalartype = { $scalartype:tt },
selfname = $selfname:literal
) => (
impl<'key $(, $($generic),+)? > Index<&'key str> for $yaml $( where $($whereclause)+ )? {
type Output = $nodetype;
fn index(&self, idx: &'key str) -> &$nodetype {
match self.as_mapping_get_impl(idx) {
Some(value) => value,
None => {
if matches!(self, Self::Mapping(_)) {
panic!("Key '{idx}' not found in {} mapping", $selfname)
} else {
panic!("Attempt to index {} with '{idx}' but it's not a mapping", $selfname)
}
}
}
}
}
impl<'key $(, $($generic),+)?> IndexMut<&'key str> for $yaml $( where $($whereclause)+ )? {
fn index_mut(&mut self, idx: &'key str) -> &mut $nodetype {
assert!(
matches!(self, Self::Mapping(_)),
"Attempt to index {} with '{idx}' but it's not a mapping", $selfname
);
match self.as_mapping_get_mut_impl(idx) {
Some(value) => value,
None => {
panic!("Key '{idx}' not found in {} mapping", $selfname)
}
}
}
}
impl $(<$($generic),+>)? Index<usize> for $yaml $( where $($whereclause)+ )? {
type Output = $nodetype;
fn index(&self, idx: usize) -> &$nodetype {
match self {
Self::Sequence(sequence) => sequence
.get(idx)
.unwrap_or_else(|| panic!("Index {idx} out of bounds in {} sequence", $selfname)),
Self::Mapping(mapping) => {
let key = i64::try_from(idx).unwrap_or_else(|_| {
panic!("Attempt to index {} mapping with overflowing index", $selfname)
});
mapping
.get(&Self::Value($scalartype::Integer(key)).into())
.unwrap_or_else(|| panic!("Key '{idx}' not found in {} mapping", $selfname))
}
_ => {
panic!(
"Attempt to index {} with {idx} but it's not a mapping nor a sequence",
$selfname
);
}
}
}
}
impl $(<$($generic),+>)? IndexMut<usize> for $yaml $( where $($whereclause)+ )? {
fn index_mut(&mut self, idx: usize) -> &mut $nodetype {
match self {
Self::Sequence(sequence) => sequence
.get_mut(idx)
.unwrap_or_else(|| panic!("Index {idx} out of bounds in {} sequence", $selfname)),
Self::Mapping(mapping) => {
let key = i64::try_from(idx).unwrap_or_else(|_| {
panic!("Attempt to index {} mapping with overflowing index", $selfname)
});
mapping
.get_mut(&Self::Value($scalartype::Integer(key)).into())
.unwrap_or_else(|| panic!("Key {idx} not found in {} mapping", $selfname))
}
_ => {
panic!(
"Attempt to index {} with {idx} but it's not a mapping nor a sequence",
$selfname
)
}
}
}
}
);
);
macro_rules! define_as (
($fn_name:ident, $t:ident, $variant:ident) => (
define_as_pattern!($fn_name, $t => Self::$variant(v) => Some(v.into()));
);
);
macro_rules! define_as_ref (
($fn_name:ident, $t:ty, $variant:ident) => (
define_as_ref_pattern!($fn_name, $t => Self::$variant(ref v) => Some(v));
);
);
macro_rules! define_as_ref_mut (
($fn_name:ident, $t:ty, $variant:ident) => (
define_as_ref_mut_pattern!($fn_name, $t => Self::$variant(ref mut v) => Some(v));
);
);
macro_rules! define_into (
($fn_name:ident, $t:ty, $variant:ident) => (
define_into_pattern!($fn_name, $t => Self::$variant(v) => Some(v.into()));
);
);
macro_rules! define_is (
($fn_name:ident, $variant:pat) => (
#[must_use]
pub fn $fn_name(&self) -> bool {
matches!(self, $variant)
}
);
);
macro_rules! define_as_pattern (
($fn_name:ident, $t:ty => $($variant:tt)+ ) => (
#[must_use]
pub fn $fn_name(&self) -> Option<$t> {
match *self {
$($variant)+,
_ => None
}
}
);
);
macro_rules! define_as_ref_pattern (
($fn_name:ident, $t:ty => $($variant:tt)+) => (
#[must_use]
pub fn $fn_name(&self) -> Option<$t> {
match self {
$($variant)+,
_ => None
}
}
);
);
macro_rules! define_as_ref_mut_pattern (
($fn_name:ident, $t:ty => $($variant:tt)+) => (
#[must_use]
pub fn $fn_name(&mut self) -> Option<$t> {
match *self {
$($variant)+,
_ => None
}
}
);
);
macro_rules! define_into_pattern (
($fn_name:ident, $t:ty => $($variant:tt)+) => (
#[must_use]
pub fn $fn_name(self) -> Option<$t> {
match self {
$($variant)+,
_ => None
}
}
);
);