use std::borrow::Cow;
use hashlink::LinkedHashMap;
use saphyr_parser::{Marker, ScalarStyle, Span, Tag};
use crate::{LoadableYamlNode, Scalar, Yaml, YamlData};
#[derive(Clone, Debug)]
pub struct MarkedYaml<'input> {
pub span: Span,
pub data: YamlData<'input, MarkedYaml<'input>>,
}
impl<'input> MarkedYaml<'input> {
#[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 {
data: YamlData::Value(Scalar::parse_from_cow(v)),
span: Span::default(),
}
}
#[must_use]
pub fn value_from_cow_and_metadata(
v: Cow<'input, str>,
style: ScalarStyle,
tag: Option<&Cow<'input, Tag>>,
) -> Self {
Scalar::parse_from_cow_and_metadata(v, style, tag).map_or_else(
|| Self {
data: YamlData::BadValue,
span: Span::default(),
},
|v| Self {
data: YamlData::Value(v),
span: Span::default(),
},
)
}
}
impl super::AnnotatedNode for MarkedYaml<'_> {
type HashKey<'a> = MarkedYaml<'a>;
fn parse_representation_recursive(&mut self) -> bool {
self.data.parse_representation_recursive()
}
}
impl<'a> From<YamlData<'a, MarkedYaml<'a>>> for MarkedYaml<'a> {
fn from(value: YamlData<'a, MarkedYaml<'a>>) -> Self {
Self {
span: Span::default(),
data: value,
}
}
}
impl<'b> PartialEq<MarkedYaml<'b>> for MarkedYaml<'_> {
fn eq(&self, other: &MarkedYaml<'b>) -> bool {
self.data.eq(&other.data)
}
}
impl Eq for MarkedYaml<'_> {}
impl std::hash::Hash for MarkedYaml<'_> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.data.hash(state);
}
}
impl<'input> LoadableYamlNode<'input> for MarkedYaml<'input> {
type HashKey = MarkedYaml<'input>;
fn from_bare_yaml(yaml: Yaml<'input>) -> Self {
Self {
span: Span::default(),
data: match yaml {
Yaml::Sequence(_) => YamlData::Sequence(vec![]),
Yaml::Mapping(_) => YamlData::Mapping(LinkedHashMap::new()),
Yaml::Alias(x) => YamlData::Alias(x),
Yaml::BadValue => YamlData::BadValue,
Yaml::Representation(v, style, tag) => YamlData::Representation(v, style, tag),
Yaml::Tagged(tag, node) => {
YamlData::Tagged(tag, Box::new(Self::from_bare_yaml(*node)))
}
Yaml::Value(x) => YamlData::Value(x),
},
}
}
fn is_sequence(&self) -> bool {
self.data.is_sequence()
}
fn is_mapping(&self) -> bool {
self.data.is_mapping()
}
fn is_badvalue(&self) -> bool {
self.data.is_badvalue()
}
fn into_tagged(self, tag: Cow<'input, Tag>) -> Self {
Self {
span: self.span,
data: YamlData::Tagged(tag, Box::new(self)),
}
}
fn sequence_mut(&mut self) -> &mut Vec<Self> {
self.data
.as_vec_mut()
.expect("Called sequence_mut on a non-array")
}
fn mapping_mut(&mut self) -> &mut LinkedHashMap<Self::HashKey, Self> {
self.data
.as_mapping_mut()
.expect("Called mapping_mut on a non-hash")
}
fn take(&mut self) -> Self {
let mut taken_out = MarkedYaml {
span: Span::default(),
data: YamlData::BadValue,
};
std::mem::swap(&mut taken_out, self);
taken_out
}
fn with_span(mut self, span: Span) -> Self {
self.span = span;
self
}
fn with_start_marker(mut self, mark: Marker) -> Self {
self.span.start = mark;
self
}
fn with_end_marker(mut self, mark: Marker) -> Self {
self.span.end = mark;
self
}
}