use std::fmt::{self, Display};
use std::slice;
#[derive(Clone, Debug, Default)]
pub struct Path {
segments: Vec<Segment>,
}
impl From<Vec<Segment>> for Path {
fn from(segments: Vec<Segment>) -> Self {
Self { segments }
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Segment {
Seq {
index: usize,
},
Map {
key: String,
},
Enum {
variant: String,
},
}
impl Path {
pub fn is_empty(&self) -> bool {
self.segments.is_empty()
}
pub fn iter(&self) -> Segments {
Segments {
iter: self.segments.iter(),
}
}
pub(crate) fn segments(&self) -> &[Segment] {
&self.segments
}
}
impl<'a> IntoIterator for &'a Path {
type Item = &'a Segment;
type IntoIter = Segments<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct Segments<'a> {
iter: slice::Iter<'a, Segment>,
}
impl<'a> Iterator for Segments<'a> {
type Item = &'a Segment;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl DoubleEndedIterator for Segments<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back()
}
}
impl ExactSizeIterator for Segments<'_> {
fn len(&self) -> usize {
self.iter.len()
}
}
impl Display for Path {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
if self.segments.is_empty() {
return formatter.write_str(".");
}
let mut separator = "";
for segment in self {
if !matches!(segment, Segment::Seq { .. }) {
formatter.write_str(separator)?;
}
write!(formatter, "{}", segment)?;
separator = ".";
}
Ok(())
}
}
impl Display for Segment {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
Segment::Seq { index } => write!(formatter, "[{}]", index),
Segment::Map { key } | Segment::Enum { variant: key } => {
write!(formatter, "{}", key)
}
}
}
}