Initial work for exposing getters and hiding the fields of the ast nodes.
Ultimately this is about semver and exposing a stable interface while allowing the internal representation to change. The fields are still pub(crate) to make constructing the types easier inside this crate, which should be fine because we can refactor the code inside this crate whenever the internal structure changes.
This commit is contained in:
parent
5e127fec11
commit
dae10c2eef
@ -3,6 +3,7 @@ use std::marker::PhantomData;
|
|||||||
use super::ast_node::AstNode;
|
use super::ast_node::AstNode;
|
||||||
use super::macros::children_iter;
|
use super::macros::children_iter;
|
||||||
use super::macros::empty_iter;
|
use super::macros::empty_iter;
|
||||||
|
use super::macros::multi_field_getter_iter;
|
||||||
use super::macros::multi_field_iter;
|
use super::macros::multi_field_iter;
|
||||||
use crate::types::AngleLink;
|
use crate::types::AngleLink;
|
||||||
use crate::types::BabelCall;
|
use crate::types::BabelCall;
|
||||||
@ -223,12 +224,12 @@ children_iter!(
|
|||||||
PlainListIter,
|
PlainListIter,
|
||||||
std::slice::Iter<'r, PlainListItem<'s>>
|
std::slice::Iter<'r, PlainListItem<'s>>
|
||||||
);
|
);
|
||||||
multi_field_iter!(
|
multi_field_getter_iter!(
|
||||||
PlainListItem<'s>,
|
PlainListItem<'s>,
|
||||||
PlainListItemIter,
|
PlainListItemIter,
|
||||||
tag,
|
get_tag,
|
||||||
std::slice::Iter<'r, Object<'s>>,
|
std::slice::Iter<'r, Object<'s>>,
|
||||||
children,
|
get_children,
|
||||||
std::slice::Iter<'r, Element<'s>>
|
std::slice::Iter<'r, Element<'s>>
|
||||||
);
|
);
|
||||||
children_iter!(
|
children_iter!(
|
||||||
|
@ -112,3 +112,43 @@ $fieldname: self.$fieldname.iter(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use multi_field_iter;
|
pub(crate) use multi_field_iter;
|
||||||
|
|
||||||
|
/// Create iterators for ast nodes using getters where it has to iterate over multiple child lists.
|
||||||
|
macro_rules! multi_field_getter_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_getter_iter;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use super::element::Element;
|
use super::element::Element;
|
||||||
use super::lesser_element::TableCell;
|
use super::lesser_element::TableCell;
|
||||||
|
use super::macros::ref_getter;
|
||||||
|
use super::macros::simple_getter;
|
||||||
use super::Keyword;
|
use super::Keyword;
|
||||||
use super::Object;
|
use super::Object;
|
||||||
use super::StandardProperties;
|
use super::StandardProperties;
|
||||||
@ -23,14 +25,14 @@ pub type IndentationLevel = u16;
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PlainListItem<'s> {
|
pub struct PlainListItem<'s> {
|
||||||
pub source: &'s str,
|
pub(crate) source: &'s str,
|
||||||
pub indentation: IndentationLevel,
|
pub(crate) indentation: IndentationLevel,
|
||||||
pub bullet: &'s str,
|
pub(crate) bullet: &'s str,
|
||||||
pub counter: Option<PlainListItemCounter>,
|
pub(crate) counter: Option<PlainListItemCounter>,
|
||||||
pub checkbox: Option<(CheckboxType, &'s str)>,
|
pub(crate) checkbox: Option<(CheckboxType, &'s str)>,
|
||||||
pub tag: Vec<Object<'s>>,
|
pub(crate) tag: Vec<Object<'s>>,
|
||||||
pub pre_blank: PlainListItemPreBlank,
|
pub(crate) pre_blank: PlainListItemPreBlank,
|
||||||
pub children: Vec<Element<'s>>,
|
pub(crate) children: Vec<Element<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PlainListItemCounter = u16;
|
pub type PlainListItemCounter = u16;
|
||||||
@ -157,3 +159,29 @@ impl<'s> StandardProperties<'s> for TableRow<'s> {
|
|||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'s> PlainListItem<'s> {
|
||||||
|
simple_getter!(get_indentation_level, indentation, IndentationLevel);
|
||||||
|
simple_getter!(
|
||||||
|
/// Get the bullet
|
||||||
|
///
|
||||||
|
/// Example output: "1. "
|
||||||
|
get_bullet,
|
||||||
|
bullet,
|
||||||
|
&'s str
|
||||||
|
);
|
||||||
|
simple_getter!(get_counter, counter, Option<PlainListItemCounter>);
|
||||||
|
simple_getter!(get_pre_blank, pre_blank, PlainListItemPreBlank);
|
||||||
|
ref_getter!(get_tag, tag, Vec<Object<'s>>);
|
||||||
|
ref_getter!(get_children, children, Vec<Element<'s>>);
|
||||||
|
|
||||||
|
pub fn get_checkbox(&self) -> Option<&'s str> {
|
||||||
|
self.checkbox.as_ref().map(|(_, checkbox)| *checkbox)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_checkbox_type(&self) -> Option<&CheckboxType> {
|
||||||
|
self.checkbox
|
||||||
|
.as_ref()
|
||||||
|
.map(|(checkbox_type, _)| checkbox_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
21
src/types/macros.rs
Normal file
21
src/types/macros.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// TODO: Would be nice if I didn't have to specify a function name but it looks like concat_idents!() cannot be used to create an ident.
|
||||||
|
// TODO: Find out if proc macros could do this easier (for example, parsing out the field type)
|
||||||
|
macro_rules! simple_getter {
|
||||||
|
($(#[$meta:meta])* $funcname: ident, $field:ident, $fieldtype:ty) => {
|
||||||
|
$(#[$meta])*
|
||||||
|
pub fn $funcname(&self) -> $fieldtype {
|
||||||
|
self.$field
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use simple_getter;
|
||||||
|
|
||||||
|
macro_rules! ref_getter {
|
||||||
|
($(#[$meta:meta])* $funcname: ident, $field:ident, $fieldtype:ty) => {
|
||||||
|
$(#[$meta])*
|
||||||
|
pub fn $funcname(&self) -> &$fieldtype {
|
||||||
|
&self.$field
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub(crate) use ref_getter;
|
@ -3,6 +3,7 @@ mod element;
|
|||||||
mod get_standard_properties;
|
mod get_standard_properties;
|
||||||
mod greater_element;
|
mod greater_element;
|
||||||
mod lesser_element;
|
mod lesser_element;
|
||||||
|
mod macros;
|
||||||
mod object;
|
mod object;
|
||||||
mod source;
|
mod source;
|
||||||
mod standard_properties;
|
mod standard_properties;
|
||||||
|
Loading…
Reference in New Issue
Block a user