Implement empty iterator for types with no ast node children.

This commit is contained in:
Tom Alexander 2023-09-27 15:38:33 -04:00
parent e4cfc296e5
commit 7419b75d76
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
3 changed files with 72 additions and 29 deletions

View File

@ -1,7 +1,13 @@
use std::marker::PhantomData;
use super::ast_node::AstNode; use super::ast_node::AstNode;
use super::macros::simple_iter;
use crate::types::Bold; use crate::types::Bold;
use crate::types::Code;
use crate::types::Italic; use crate::types::Italic;
use crate::types::Object; use crate::types::Object;
use crate::types::StrikeThrough;
use crate::types::Underline;
pub enum AstNodeIter<'r, 's> { pub enum AstNodeIter<'r, 's> {
// Document Nodes // Document Nodes
@ -34,9 +40,9 @@ pub enum AstNodeIter<'r, 's> {
// Objects // Objects
Bold(BoldIter<'r, 's>), Bold(BoldIter<'r, 's>),
Italic(ItalicIter<'r, 's>), Italic(ItalicIter<'r, 's>),
// Underline(UnderlineIter<'r, 's>), Underline(UnderlineIter<'r, 's>),
// StrikeThrough(StrikeThroughIter<'r, 's>), StrikeThrough(StrikeThroughIter<'r, 's>),
// Code(CodeIter<'r, 's>), Code(CodeIter<'r, 's>),
// Verbatim(VerbatimIter<'r, 's>), // Verbatim(VerbatimIter<'r, 's>),
// PlainText(PlainTextIter<'r, 's>), // PlainText(PlainTextIter<'r, 's>),
// RegularLink(RegularLinkIter<'r, 's>), // RegularLink(RegularLinkIter<'r, 's>),
@ -85,32 +91,38 @@ impl<'r, 's> IntoIterator for &'r Bold<'s> {
} }
} }
macro_rules! simple_iter { simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>);
($astnodetype:ty, $itertype:ident, $innertype:ty) => { simple_iter!(
pub struct $itertype<'r, 's> { Underline<'s>,
next: $innertype, UnderlineIter,
} std::slice::Iter<'r, Object<'s>>
);
simple_iter!(
StrikeThrough<'s>,
StrikeThroughIter,
std::slice::Iter<'r, Object<'s>>
);
impl<'r, 's> Iterator for $itertype<'r, 's> { pub struct CodeIter<'r, 's> {
type Item = AstNode<'r, 's>; phantom: PhantomData<&'r Code<'s>>,
fn next(&mut self) -> Option<Self::Item> {
self.next.next().map(Into::<AstNode>::into)
}
}
impl<'r, 's> IntoIterator for &'r $astnodetype {
type Item = AstNode<'r, 's>;
type IntoIter = $itertype<'r, 's>;
fn into_iter(self) -> Self::IntoIter {
$itertype {
next: self.children.iter(),
}
}
}
};
} }
simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); impl<'r, 's> Iterator for CodeIter<'r, 's> {
type Item = AstNode<'r, 's>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl<'r, 's> IntoIterator for &'r Code<'s> {
type Item = AstNode<'r, 's>;
type IntoIter = CodeIter<'r, 's>;
fn into_iter(self) -> Self::IntoIter {
CodeIter {
phantom: PhantomData,
}
}
}

30
src/iter/macros.rs Normal file
View File

@ -0,0 +1,30 @@
/// Create iterators for ast nodes where it only has to iterate over children
macro_rules! simple_iter {
($astnodetype:ty, $itertype:ident, $innertype:ty) => {
pub struct $itertype<'r, 's> {
next: $innertype,
}
impl<'r, 's> Iterator for $itertype<'r, 's> {
type Item = AstNode<'r, 's>;
fn next(&mut self) -> Option<Self::Item> {
self.next.next().map(Into::<AstNode>::into)
}
}
impl<'r, 's> IntoIterator for &'r $astnodetype {
type Item = AstNode<'r, 's>;
type IntoIter = $itertype<'r, 's>;
fn into_iter(self) -> Self::IntoIter {
$itertype {
next: self.children.iter(),
}
}
}
};
}
pub(crate) use simple_iter;

View File

@ -1,2 +1,3 @@
mod ast_node; mod ast_node;
mod ast_node_iter; mod ast_node_iter;
mod macros;