Skip to content

Commit

Permalink
Merge pull request #153 from sftse/unwraps
Browse files Browse the repository at this point in the history
Rework a little to remove unwraps.
  • Loading branch information
jugglerchris authored May 25, 2024
2 parents 59516b7 + caf36ad commit 7d8d471
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 71 deletions.
42 changes: 18 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -979,67 +979,62 @@ where
to_process: std::vec::IntoIter<N>,
}

let mut pending_stack = vec![PendingNode {
let mut last = PendingNode {
// We only expect one child, which we'll just return.
construct: Box::new(|_, mut cs| Ok(cs.pop())),
prefn: None,
postfn: None,
children: Vec::new(),
to_process: vec![top].into_iter(),
}];
};
let mut pending_stack = Vec::new();
loop {
// Get the next child node to process
let next_node = pending_stack.last_mut().unwrap().to_process.next();
if let Some(h) = next_node {
pending_stack
.last_mut()
.unwrap()
.prefn
if let Some(h) = last.to_process.next() {
last.prefn
.as_ref()
.map(|ref f| f(context, &h))
.transpose()?;
match process_node(context, h)? {
TreeMapResult::Finished(result) => {
pending_stack
.last_mut()
.unwrap()
.postfn
.as_ref()
.map(|ref f| f(context, &result));
pending_stack.last_mut().unwrap().children.push(result);
last.postfn.as_ref().map(|ref f| f(context, &result));
last.children.push(result);
}
TreeMapResult::PendingChildren {
children,
cons,
prefn,
postfn,
} => {
pending_stack.push(PendingNode {
pending_stack.push(last);
last = PendingNode {
construct: cons,
prefn,
postfn,
children: Vec::new(),
to_process: children.into_iter(),
});
};
}
TreeMapResult::Nothing => {}
};
} else {
// No more children, so finally construct the parent.
let completed = pending_stack.pop().unwrap();
let reduced = (completed.construct)(context, completed.children)?;
let reduced = (last.construct)(context, last.children)?;
let parent = pending_stack.pop();
if let Some(node) = reduced {
if let Some(parent) = pending_stack.last_mut() {
if let Some(mut parent) = parent {
parent.postfn.as_ref().map(|ref f| f(context, &node));
parent.children.push(node);
last = parent;
} else {
// Finished the whole stack!
break Ok(Some(node));
}
} else {
/* Finished the stack, and have nothing */
if pending_stack.is_empty() {
break Ok(None);
match parent {
Some(parent) => last = parent,
None => break Ok(None),
}
}
}
Expand Down Expand Up @@ -2336,8 +2331,7 @@ fn parse_with_context(mut input: impl io::Read, context: &mut HtmlContext) -> Re
};
let dom = parse_document(RcDom::default(), opts)
.from_utf8()
.read_from(&mut input)
.unwrap();
.read_from(&mut input)?;
let render_tree =
dom_to_render_tree_with_context(dom.document.clone(), &mut Discard {}, context)?
.ok_or(Error::Fail)?;
Expand Down
77 changes: 30 additions & 47 deletions src/render/text_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,10 @@ impl<T: Debug + Eq + PartialEq + Clone + Default> TaggedLine<T> {
fn push_str(&mut self, ts: TaggedString<T>) {
use self::TaggedLineElement::Str;

if !self.v.is_empty() {
if let Str(ref mut ts_prev) = self.v.last_mut().unwrap() {
if ts_prev.tag == ts.tag {
ts_prev.s.push_str(&ts.s);
return;
}
if let Some(Str(ts_prev)) = self.v.last_mut() {
if ts_prev.tag == ts.tag {
ts_prev.s.push_str(&ts.s);
return;
}
}
self.v.push(Str(ts));
Expand Down Expand Up @@ -206,12 +204,10 @@ impl<T: Debug + Eq + PartialEq + Clone + Default> TaggedLine<T> {
fn push_char(&mut self, c: char, tag: &T) {
use self::TaggedLineElement::Str;

if !self.v.is_empty() {
if let Str(ref mut ts_prev) = self.v.last_mut().unwrap() {
if ts_prev.tag == *tag {
ts_prev.s.push(c);
return;
}
if let Some(Str(ts_prev)) = self.v.last_mut() {
if ts_prev.tag == *tag {
ts_prev.s.push(c);
return;
}
}
let mut s = String::new();
Expand Down Expand Up @@ -954,6 +950,24 @@ impl Default for RenderOptions {
}
}

fn get_wrapping_or_insert<'w, D: TextDecorator>(
wrapping: &'w mut Option<WrappedBlock<Vec<D::Annotation>>>,
options: &RenderOptions,
width: usize,
) -> &'w mut WrappedBlock<Vec<D::Annotation>> {
wrapping.get_or_insert_with(|| {
let wwidth = match options.wrap_width {
Some(ww) => ww.min(width),
None => width,
};
WrappedBlock::new(
wwidth,
options.pad_block_width,
options.allow_width_overflow,
)
})
}

impl<D: TextDecorator> SubRenderer<D> {
/// Render links as lines
pub fn finalise(&mut self, links: Vec<String>) -> Vec<TaggedLine<D::Annotation>> {
Expand All @@ -976,27 +990,6 @@ impl<D: TextDecorator> SubRenderer<D> {
}
}

fn ensure_wrapping_exists(&mut self) {
if self.wrapping.is_none() {
let wwidth = match self.options.wrap_width {
Some(ww) => ww.min(self.width),
None => self.width,
};
self.wrapping = Some(WrappedBlock::new(
wwidth,
self.options.pad_block_width,
self.options.allow_width_overflow,
));
}
}

/// Get the current line wrapping context (and create if
/// needed).
fn current_text(&mut self) -> &mut WrappedBlock<Vec<D::Annotation>> {
self.ensure_wrapping_exists();
self.wrapping.as_mut().unwrap()
}

/// Add a prerendered (multiline) string with the current annotations.
fn add_subblock(&mut self, s: &str) {
use self::TaggedLineElement::Str;
Expand Down Expand Up @@ -1226,8 +1219,6 @@ impl<D: TextDecorator> Renderer for SubRenderer<D> {
if self.at_block_end {
self.start_block()?;
}
// ensure wrapping is set
let _ = self.current_text();
let mut s = None;
// Do any filtering of the text
for filter in &self.text_filter_stack {
Expand All @@ -1238,20 +1229,15 @@ impl<D: TextDecorator> Renderer for SubRenderer<D> {
}
let filtered_text = s.as_deref().unwrap_or(text);
if self.pre_depth == 0 {
self.wrapping
.as_mut()
.unwrap()
get_wrapping_or_insert::<D>(&mut self.wrapping, &self.options, self.width)
.add_text(filtered_text, &self.ann_stack)?;
} else {
let mut tag_first = self.ann_stack.clone();
let mut tag_cont = self.ann_stack.clone();
tag_first.push(self.decorator.decorate_preformat_first());
tag_cont.push(self.decorator.decorate_preformat_cont());
self.wrapping.as_mut().unwrap().add_preformatted_text(
filtered_text,
&tag_first,
&tag_cont,
)?;
get_wrapping_or_insert::<D>(&mut self.wrapping, &self.options, self.width)
.add_preformatted_text(filtered_text, &tag_first, &tag_cont)?;
}
Ok(())
}
Expand Down Expand Up @@ -1591,10 +1577,7 @@ impl<D: TextDecorator> Renderer for SubRenderer<D> {
fn record_frag_start(&mut self, fragname: &str) {
use self::TaggedLineElement::FragmentStart;

self.ensure_wrapping_exists();
self.wrapping
.as_mut()
.unwrap()
get_wrapping_or_insert::<D>(&mut self.wrapping, &self.options, self.width)
.add_element(FragmentStart(fragname.to_string()));
}

Expand Down

0 comments on commit 7d8d471

Please sign in to comment.