lib: add Render::{push, write}_borrowed
allow rendering iterators with borrowed events resolves #24
This commit is contained in:
		
					parent
					
						
							
								e8503e28fd
							
						
					
				
			
			
				commit
				
					
						10788af246
					
				
			
		
					 1 changed files with 75 additions and 26 deletions
				
			
		
							
								
								
									
										99
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										99
									
								
								src/lib.rs
									
										
									
									
									
								
							| 
						 | 
					@ -71,6 +71,9 @@ type CowStr<'s> = std::borrow::Cow<'s, str>;
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// The output can be written to either a [`std::fmt::Write`] or a [`std::io::Write`] object.
 | 
					/// The output can be written to either a [`std::fmt::Write`] or a [`std::io::Write`] object.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
					/// If ownership of the [`Event`]s cannot be given to the renderer, use [`Render::push_borrowed`]
 | 
				
			||||||
 | 
					/// or [`Render::write_borrowed`].
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
/// An implementor needs to at least implement the [`Render::render_event`] function that renders a
 | 
					/// An implementor needs to at least implement the [`Render::render_event`] function that renders a
 | 
				
			||||||
/// single event to the output. If anything needs to be rendered at the beginning or end of the
 | 
					/// single event to the output. If anything needs to be rendered at the beginning or end of the
 | 
				
			||||||
/// output, the [`Render::render_prologue`] and [`Render::render_epilogue`] can be implemented as
 | 
					/// output, the [`Render::render_prologue`] and [`Render::render_epilogue`] can be implemented as
 | 
				
			||||||
| 
						 | 
					@ -136,7 +139,7 @@ pub trait Render {
 | 
				
			||||||
        self.render_epilogue(&mut out)
 | 
					        self.render_epilogue(&mut out)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Write [`Event`]s to a byte sink, encoded as UTF-8.
 | 
					    /// Write owned [`Event`]s to a byte sink, encoded as UTF-8.
 | 
				
			||||||
    ///
 | 
					    ///
 | 
				
			||||||
    /// NOTE: This performs many small writes, so IO writes should be buffered with e.g.
 | 
					    /// NOTE: This performs many small writes, so IO writes should be buffered with e.g.
 | 
				
			||||||
    /// [`std::io::BufWriter`].
 | 
					    /// [`std::io::BufWriter`].
 | 
				
			||||||
| 
						 | 
					@ -145,35 +148,81 @@ pub trait Render {
 | 
				
			||||||
        I: Iterator<Item = Event<'s>>,
 | 
					        I: Iterator<Item = Event<'s>>,
 | 
				
			||||||
        W: io::Write,
 | 
					        W: io::Write,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        struct Adapter<T: io::Write> {
 | 
					        let mut out = WriteAdapter {
 | 
				
			||||||
            inner: T,
 | 
					 | 
				
			||||||
            error: io::Result<()>,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        impl<T: io::Write> fmt::Write for Adapter<T> {
 | 
					 | 
				
			||||||
            fn write_str(&mut self, s: &str) -> fmt::Result {
 | 
					 | 
				
			||||||
                match self.inner.write_all(s.as_bytes()) {
 | 
					 | 
				
			||||||
                    Ok(()) => Ok(()),
 | 
					 | 
				
			||||||
                    Err(e) => {
 | 
					 | 
				
			||||||
                        self.error = Err(e);
 | 
					 | 
				
			||||||
                        Err(fmt::Error)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let mut out = Adapter {
 | 
					 | 
				
			||||||
            inner: out,
 | 
					            inner: out,
 | 
				
			||||||
            error: Ok(()),
 | 
					            error: Ok(()),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match self.push(events, &mut out) {
 | 
					        self.push(events, &mut out).map_err(|_| match out.error {
 | 
				
			||||||
            Ok(()) => Ok(()),
 | 
					            Err(e) => e,
 | 
				
			||||||
            Err(_) => match out.error {
 | 
					            _ => io::Error::new(io::ErrorKind::Other, "formatter error"),
 | 
				
			||||||
                Err(_) => out.error,
 | 
					        })
 | 
				
			||||||
                _ => Err(io::Error::new(io::ErrorKind::Other, "formatter error")),
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Push borrowed [`Event`]s to a unicode-accepting buffer or stream.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// # Examples
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// Render a borrowed slice of [`Event`]s.
 | 
				
			||||||
 | 
					    /// ```
 | 
				
			||||||
 | 
					    /// # use jotdown::Render;
 | 
				
			||||||
 | 
					    /// # let events: &[jotdown::Event] = &[];
 | 
				
			||||||
 | 
					    /// let mut output = String::new();
 | 
				
			||||||
 | 
					    /// let mut renderer = jotdown::html::Renderer::default();
 | 
				
			||||||
 | 
					    /// renderer.push_borrowed(events.iter(), &mut output);
 | 
				
			||||||
 | 
					    /// ```
 | 
				
			||||||
 | 
					    fn push_borrowed<'s, E, I, W>(&mut self, mut events: I, mut out: W) -> fmt::Result
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        E: AsRef<Event<'s>>,
 | 
				
			||||||
 | 
					        I: Iterator<Item = E>,
 | 
				
			||||||
 | 
					        W: fmt::Write,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        self.render_prologue(&mut out)?;
 | 
				
			||||||
 | 
					        events.try_for_each(|e| self.render_event(e.as_ref(), &mut out))?;
 | 
				
			||||||
 | 
					        self.render_epilogue(&mut out)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Write borrowed [`Event`]s to a byte sink, encoded as UTF-8.
 | 
				
			||||||
 | 
					    ///
 | 
				
			||||||
 | 
					    /// NOTE: This performs many small writes, so IO writes should be buffered with e.g.
 | 
				
			||||||
 | 
					    /// [`std::io::BufWriter`].
 | 
				
			||||||
 | 
					    fn write_borrowed<'s, E, I, W>(&mut self, events: I, out: W) -> io::Result<()>
 | 
				
			||||||
 | 
					    where
 | 
				
			||||||
 | 
					        E: AsRef<Event<'s>>,
 | 
				
			||||||
 | 
					        I: Iterator<Item = E>,
 | 
				
			||||||
 | 
					        W: io::Write,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        let mut out = WriteAdapter {
 | 
				
			||||||
 | 
					            inner: out,
 | 
				
			||||||
 | 
					            error: Ok(()),
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.push_borrowed(events, &mut out)
 | 
				
			||||||
 | 
					            .map_err(|_| match out.error {
 | 
				
			||||||
 | 
					                Err(e) => e,
 | 
				
			||||||
 | 
					                _ => io::Error::new(io::ErrorKind::Other, "formatter error"),
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct WriteAdapter<T: io::Write> {
 | 
				
			||||||
 | 
					    inner: T,
 | 
				
			||||||
 | 
					    error: io::Result<()>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T: io::Write> fmt::Write for WriteAdapter<T> {
 | 
				
			||||||
 | 
					    fn write_str(&mut self, s: &str) -> fmt::Result {
 | 
				
			||||||
 | 
					        self.inner.write_all(s.as_bytes()).map_err(|e| {
 | 
				
			||||||
 | 
					            self.error = Err(e);
 | 
				
			||||||
 | 
					            fmt::Error
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// XXX why is this not a blanket implementation?
 | 
				
			||||||
 | 
					impl<'s> AsRef<Event<'s>> for &Event<'s> {
 | 
				
			||||||
 | 
					    fn as_ref(&self) -> &Event<'s> {
 | 
				
			||||||
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue