Reduced some of the code duplication

This commit is contained in:
Michael Bryan 2017-09-02 18:21:37 +08:00
parent e89e6a04cd
commit 227f40679e
1 changed files with 52 additions and 52 deletions

View File

@ -241,9 +241,8 @@ impl<'a> SummaryParser<'a> {
match self.state { match self.state {
State::Begin => self.step_start(next_event)?, State::Begin => self.step_start(next_event)?,
State::PrefixChapters => self.step_prefix(next_event)?, State::PrefixChapters | State::SuffixChapters => self.step_affix(next_event)?,
State::NumberedChapters(_) => self.step_numbered(next_event)?, State::NumberedChapters(_) => self.step_numbered(next_event)?,
State::SuffixChapters => self.step_suffix(next_event)?,
State::End => {}, State::End => {},
} }
} else { } else {
@ -266,31 +265,22 @@ impl<'a> SummaryParser<'a> {
Ok(()) Ok(())
} }
/// In the second step we look out for links and horizontal rules to add /// Try to step through an "affix" section (recognising prefix and suffix
/// to the prefix. /// chapters).
/// ///
/// This state should only progress when it encounters a list. All other /// If we encounter a link or horizontal line, it'll get added to the
/// events will either be separators (horizontal rule), prefix chapters /// section. If we encounter a list, we'll either change to
/// (the links), or skipped. /// `State::NumberedChapter` (for prefix) or throw an error (suffix chapters).
fn step_prefix(&mut self, event: Event<'a>) -> Result<()> { ///
/// Anything else will be ignored.
fn step_affix(&mut self, event: Event<'a>) -> Result<()> {
match event { match event {
Event::Start(Tag::Link(location, _)) => { Event::Start(tag) => self.handle_start_tag_in_affix_chapter(tag)?,
let content = collect_events!(self.stream, Tag::Link(_, _));
let text = stringify_events(content);
let link = Link::new(text, location.as_ref());
debug!("[*] Found a prefix chapter: {:?}", link.name);
self.summary.prefix_chapters.push(SummaryItem::Link(link));
},
Event::End(Tag::Rule) => { Event::End(Tag::Rule) => {
debug!("[*] Found a prefix chapter separator"); debug!("[*] Found an affix chapter separator");
self.summary.prefix_chapters.push(SummaryItem::Separator); self.affix_chapter_list().push(SummaryItem::Separator);
}, },
Event::Start(Tag::List(_)) => {
debug!("[*] Changing from prefix chapters to numbered chapters");
self.state = State::NumberedChapters(0);
},
other => { other => {
trace!("[*] Skipping unexpected token in summary: {:?}", other); trace!("[*] Skipping unexpected token in summary: {:?}", other);
}, },
@ -299,6 +289,42 @@ impl<'a> SummaryParser<'a> {
Ok(()) Ok(())
} }
/// A helper function to get the `SummaryItem` list we should add items to
/// when parsing an affix chapter (i.e. prefix or suffix chapters).
fn affix_chapter_list(&mut self) -> &mut Vec<SummaryItem> {
match self.state {
State::PrefixChapters => &mut self.summary.prefix_chapters,
State::SuffixChapters => &mut self.summary.suffix_chapters,
other => panic!("affix_chapter_list() called with invalid state: {:?}", other),
}
}
fn handle_start_tag_in_affix_chapter(&mut self, tag: Tag) -> Result<()> {
match tag {
Tag::Link(location, _) => {
let content = collect_events!(self.stream, Tag::Link(_, _));
let text = stringify_events(content);
let link = Link::new(text, location.as_ref());
debug!("[*] Found an affix chapter: {:?}", link.name);
self.affix_chapter_list().push(SummaryItem::Link(link));
},
Tag::List(_) => {
match self.state {
State::PrefixChapters => {
debug!("[*] Changing from prefix chapters to numbered chapters");
self.state = State::NumberedChapters(0);
},
State::SuffixChapters => bail!("Suffix chapters can't be followed by a list"),
_ => unreachable!(),
}
},
other => trace!("[*] Skipping unknown start tag while parsing affix chapters: {:?}", other),
}
Ok(())
}
/// Parse the numbered chapters. /// Parse the numbered chapters.
/// ///
/// If the event is the start of a list item, consume the entire item and /// If the event is the start of a list item, consume the entire item and
@ -352,30 +378,6 @@ impl<'a> SummaryParser<'a> {
Ok(()) Ok(())
} }
fn step_suffix(&mut self, event: Event<'a>) -> Result<()> {
// FIXME: This has been copy/pasted from step_prefix. make DRY.
match event {
Event::Start(Tag::Link(location, _)) => {
let content = collect_events!(self.stream, Tag::Link(_, _));
let text = stringify_events(content);
let link = Link::new(text, location.as_ref());
debug!("[*] Found a suffix chapter: {:?}", link.name);
self.summary.suffix_chapters.push(SummaryItem::Link(link));
},
Event::End(Tag::Rule) => {
debug!("[*] Found a suffix chapter separator");
self.summary.suffix_chapters.push(SummaryItem::Separator);
},
other => {
trace!("[*] Skipping unexpected token in summary: {:?}", other);
},
}
Ok(())
}
/// Parse a single item (`[Some Chapter Name](./path/to/chapter.md)`). /// Parse a single item (`[Some Chapter Name](./path/to/chapter.md)`).
fn parse_item(&mut self) -> Result<Link> { fn parse_item(&mut self) -> Result<Link> {
let next = self.stream.next(); let next = self.stream.next();
@ -493,7 +495,7 @@ impl Display for SectionNumber {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let dotted_number: String = self.0 let dotted_number: String = self.0
.iter() .iter()
.map(|i| format!("{}", i)) .map(|i| i.to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("."); .join(".");
@ -527,10 +529,8 @@ mod tests {
]; ];
for (input, should_be) in inputs { for (input, should_be) in inputs {
let section_number = SectionNumber(input); let section_number = SectionNumber(input).to_string();
let string_repr = format!("{}", section_number); assert_eq!(section_number, should_be);
assert_eq!(string_repr, should_be);
} }
} }