Implement a macro for iterators with multiple fields.
This commit is contained in:
		
							parent
							
								
									d8c52568db
								
							
						
					
					
						commit
						32a7ce3f36
					
				| @ -3,6 +3,7 @@ use std::marker::PhantomData; | ||||
| use super::ast_node::AstNode; | ||||
| use super::macros::children_iter; | ||||
| use super::macros::empty_iter; | ||||
| use super::macros::multi_field_iter; | ||||
| use crate::types::Bold; | ||||
| use crate::types::Code; | ||||
| use crate::types::Document; | ||||
| @ -35,6 +36,7 @@ pub enum AstNodeIter<'r, 's> { | ||||
|     // Elements
 | ||||
|     Paragraph(ParagraphIter<'r, 's>), | ||||
|     PlainList(PlainListIter<'r, 's>), | ||||
|     PlainListItem(PlainListItemIter<'r, 's>), | ||||
|     // GreaterBlock(GreaterBlockIter<'r, 's>),
 | ||||
|     // DynamicBlock(DynamicBlockIter<'r, 's>),
 | ||||
|     // FootnoteDefinition(FootnoteDefinitionIter<'r, 's>),
 | ||||
| @ -154,6 +156,15 @@ children_iter!( | ||||
|     PlainListIter, | ||||
|     std::slice::Iter<'r, PlainListItem<'s>> | ||||
| ); | ||||
| 
 | ||||
| multi_field_iter!( | ||||
|     PlainListItem<'s>, | ||||
|     PlainListItemIter, | ||||
|     tag, | ||||
|     std::slice::Iter<'r, Object<'s>>, | ||||
|     children, | ||||
|     std::slice::Iter<'r, Element<'s>> | ||||
| ); | ||||
| children_iter!(Bold<'s>, BoldIter, std::slice::Iter<'r, Object<'s>>); | ||||
| children_iter!(Italic<'s>, ItalicIter, std::slice::Iter<'r, Object<'s>>); | ||||
| children_iter!( | ||||
|  | ||||
| @ -72,3 +72,43 @@ macro_rules! empty_iter { | ||||
| } | ||||
| 
 | ||||
| pub(crate) use empty_iter; | ||||
| 
 | ||||
| /// Create iterators for ast nodes where it has to iterate over multiple child lists.
 | ||||
| macro_rules! multi_field_iter { | ||||
|     ($astnodetype:ty, $itertype:ident, $firstfieldname: ident, $firstinnertype:ty, $($fieldname: ident, $innertype:ty),*) => { | ||||
|         pub struct $itertype<'r, 's> { | ||||
|             $firstfieldname: $firstinnertype, | ||||
|             $( | ||||
| $fieldname: $innertype, | ||||
| ),* | ||||
|         } | ||||
| 
 | ||||
|         impl<'r, 's> Iterator for $itertype<'r, 's> { | ||||
|             type Item = AstNode<'r, 's>; | ||||
| 
 | ||||
|             fn next(&mut self) -> Option<Self::Item> { | ||||
|                 self.$firstfieldname.next().map(Into::<AstNode>::into) | ||||
|                 $( | ||||
| .or_else(|| self.$fieldname.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 { | ||||
|             $firstfieldname: self.$firstfieldname.iter(), | ||||
|             $( | ||||
| $fieldname: self.$fieldname.iter(), | ||||
| ),* | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| pub(crate) use multi_field_iter; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tom Alexander
						Tom Alexander