Introduce a macro for empty iterators.

This commit is contained in:
Tom Alexander 2023-09-27 15:47:01 -04:00
parent 7419b75d76
commit 4359fc9266
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
2 changed files with 47 additions and 7 deletions

View File

@ -1,14 +1,21 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use super::ast_node::AstNode; use super::ast_node::AstNode;
use super::macros::simple_iter; use super::macros::children_iter;
use super::macros::empty_iter;
use crate::types::Bold; use crate::types::Bold;
use crate::types::Code; 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::StrikeThrough;
use crate::types::Underline; use crate::types::Underline;
use crate::types::Verbatim;
/// Iterator over the AST nodes contained within the starting node.
///
/// This only iterates over the children, not the starting node itself. So an AstNodeIter::PlainList would only return PlainListItems, not the PlainList.
///
/// This only iterates over AST nodes, so an AstNodeIter::Heading would iterate over both the title and section contents, but it would not iterate over simple strings like the TODO keyword or priority.
pub enum AstNodeIter<'r, 's> { pub enum AstNodeIter<'r, 's> {
// Document Nodes // Document Nodes
// Document(DocumentIter<'r, 's>), // Document(DocumentIter<'r, 's>),
@ -43,7 +50,7 @@ pub enum AstNodeIter<'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>),
// RadioLink(RadioLinkIter<'r, 's>), // RadioLink(RadioLinkIter<'r, 's>),
@ -91,13 +98,13 @@ impl<'r, 's> IntoIterator for &'r Bold<'s> {
} }
} }
simple_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>);
simple_iter!( children_iter!(
Underline<'s>, Underline<'s>,
UnderlineIter, UnderlineIter,
std::slice::Iter<'r, Object<'s>> std::slice::Iter<'r, Object<'s>>
); );
simple_iter!( children_iter!(
StrikeThrough<'s>, StrikeThrough<'s>,
StrikeThroughIter, StrikeThroughIter,
std::slice::Iter<'r, Object<'s>> std::slice::Iter<'r, Object<'s>>
@ -126,3 +133,5 @@ impl<'r, 's> IntoIterator for &'r Code<'s> {
} }
} }
} }
empty_iter!(Verbatim<'s>, VerbatimIter);

View File

@ -1,5 +1,5 @@
/// Create iterators for ast nodes where it only has to iterate over children /// Create iterators for ast nodes where it only has to iterate over children
macro_rules! simple_iter { macro_rules! children_iter {
($astnodetype:ty, $itertype:ident, $innertype:ty) => { ($astnodetype:ty, $itertype:ident, $innertype:ty) => {
pub struct $itertype<'r, 's> { pub struct $itertype<'r, 's> {
next: $innertype, next: $innertype,
@ -27,4 +27,35 @@ macro_rules! simple_iter {
}; };
} }
pub(crate) use simple_iter; pub(crate) use children_iter;
/// Create iterators for ast nodes that do not contain any ast node children.
macro_rules! empty_iter {
($astnodetype:ty, $itertype:ident) => {
pub struct $itertype<'r, 's> {
phantom: PhantomData<&'r $astnodetype>,
}
impl<'r, 's> Iterator for $itertype<'r, 's> {
type Item = AstNode<'r, 's>;
fn next(&mut self) -> Option<Self::Item> {
None
}
}
impl<'r, 's> IntoIterator for &'r $astnodetype {
type Item = AstNode<'r, 's>;
type IntoIter = $itertype<'r, 's>;
fn into_iter(self) -> Self::IntoIter {
$itertype {
phantom: PhantomData,
}
}
}
};
}
pub(crate) use empty_iter;