use std::ops::Range;
use std::slice::Iter;
#[derive(Clone)]
pub struct TagIter<'a> {
source: &'a str,
iter: Iter<'a, (Range<usize>, Option<Range<usize>>)>,
}
impl<'a> TagIter<'a> {
#[doc(hidden)]
pub fn new(
source: &'a str,
iter: Iter<'a, (Range<usize>, Option<Range<usize>>)>,
) -> TagIter<'a> {
TagIter {
source: source,
iter: iter,
}
}
}
impl<'a> Iterator for TagIter<'a> {
type Item = (&'a str, Option<&'a str>);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|&(ref key, ref value)| {
(
&self.source[key.clone()],
value.clone().map(|value| &self.source[value]),
)
})
}
}
impl<'a> DoubleEndedIterator for TagIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|&(ref key, ref value)| {
(
&self.source[key.clone()],
value.clone().map(|value| &self.source[value]),
)
})
}
}
pub trait Tag<'a> {
fn name() -> &'static str;
fn parse(tag: Option<&'a str>) -> Option<Self>
where
Self: Sized;
fn try_match(mut tags: TagIter<'a>) -> Option<Self>
where
Self: Sized,
{
tags.find(|&(key, _)| key == Self::name())
.and_then(|(_, value)| Self::parse(value))
}
}