use crate::{Template, Section};
use crate::encoding::Encoder;
use std::borrow::Borrow;
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
pub trait Content: Sized {
fn is_truthy(&self) -> bool {
true
}
fn capacity_hint(&self, _tpl: &Template) -> usize {
0
}
fn render_escaped<'section, E>(&self, _encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
Ok(())
}
fn render_unescaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
self.render_escaped(encoder)
}
fn render_cmark<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
self.render_escaped(encoder)
}
fn render_section<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if self.is_truthy() {
section.render_once(self, encoder)
} else {
Ok(())
}
}
fn render_inverse<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if !self.is_truthy() {
section.render_once(self, encoder)
} else {
Ok(())
}
}
fn render_field_escaped<E>(&self, _hash: u64, _name: &str, _encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
Ok(())
}
fn render_field_unescaped<E>(&self, _hash: u64, _name: &str, _encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
Ok(())
}
fn render_field_section<'section, E>(&self, _hash: u64, _name: &str, _section: Section<'section>, _encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
Ok(())
}
fn render_field_inverse<'section, E>(&self, _hash: u64, _name: &str, _section: Section<'section>, _encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
Ok(())
}
}
impl Content for &str {
fn is_truthy(&self) -> bool {
self.len() != 0
}
fn capacity_hint(&self, _tpl: &Template) -> usize {
self.len()
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.write_escaped(*self)
}
fn render_unescaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.write_unescaped(*self)
}
fn render_cmark<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
crate::cmark::encode(*self, encoder)
}
}
impl Content for String {
fn is_truthy(&self) -> bool {
self.len() != 0
}
fn capacity_hint(&self, _tpl: &Template) -> usize {
self.len()
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.write_escaped(self)
}
fn render_unescaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.write_unescaped(self)
}
fn render_cmark<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
crate::cmark::encode(self, encoder)
}
}
impl Content for bool {
fn is_truthy(&self) -> bool {
*self
}
fn capacity_hint(&self, _tpl: &Template) -> usize {
5
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.write_unescaped(match *self {
true => "true",
false => "false",
})
}
}
macro_rules! impl_number_types {
($( $ty:ty ),*) => {
$(
impl Content for $ty {
fn is_truthy(&self) -> bool {
*self != 0 as $ty
}
fn capacity_hint(&self, _tpl: &Template) -> usize {
5
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.format_unescaped(self)
}
}
)*
}
}
impl_number_types!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, f32, f64);
impl<T: Content> Content for Option<T> {
fn is_truthy(&self) -> bool {
self.is_some()
}
fn capacity_hint(&self, tpl: &Template) -> usize {
match self {
Some(inner) => inner.capacity_hint(tpl),
_ => 0
}
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Some(inner) = self {
inner.render_escaped(encoder)?;
}
Ok(())
}
fn render_unescaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Some(ref inner) = self {
inner.render_unescaped(encoder)?;
}
Ok(())
}
fn render_section<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Some(item) = self {
section.render_once(item, encoder)?;
}
Ok(())
}
}
impl<T: Content, U> Content for Result<T, U> {
fn is_truthy(&self) -> bool {
self.is_ok()
}
fn capacity_hint(&self, tpl: &Template) -> usize {
match self {
Ok(inner) => inner.capacity_hint(tpl),
_ => 0
}
}
fn render_escaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Ok(inner) = self {
inner.render_escaped(encoder)?;
}
Ok(())
}
fn render_unescaped<'section, E>(&self, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Ok(ref inner) = self {
inner.render_unescaped(encoder)?;
}
Ok(())
}
fn render_section<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
if let Ok(item) = self {
section.render_once(item, encoder)?;
}
Ok(())
}
}
impl<T: Content> Content for Vec<T> {
fn is_truthy(&self) -> bool {
self.len() != 0
}
fn render_section<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
for item in self.iter() {
section.render_once(item, encoder)?;
}
Ok(())
}
}
impl<T: Content> Content for &[T] {
fn is_truthy(&self) -> bool {
self.len() != 0
}
fn render_section<'section, E>(&self, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
for item in self.iter() {
section.render_once(item, encoder)?;
}
Ok(())
}
}
impl<K, V> Content for HashMap<K, V>
where
K: Borrow<str> + Hash + Eq,
V: Content,
{
fn is_truthy(&self) -> bool {
!self.is_empty()
}
fn render_field_escaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_escaped(encoder),
None => Ok(())
}
}
fn render_field_unescaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_unescaped(encoder),
None => Ok(())
}
}
fn render_field_section<'section, E>(&self, _: u64, name: &str, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_section(section, encoder),
None => Ok(())
}
}
fn render_field_inverse<'section, E>(&self, _: u64, name: &str, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_inverse(section, encoder),
None => Ok(())
}
}
}
impl<K, V> Content for BTreeMap<K, V>
where
K: Borrow<str> + Ord,
V: Content,
{
fn is_truthy(&self) -> bool {
!self.is_empty()
}
fn render_field_escaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_escaped(encoder),
None => Ok(())
}
}
fn render_field_unescaped<E>(&self, _: u64, name: &str, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_unescaped(encoder),
None => Ok(())
}
}
fn render_field_section<'section, E>(&self, _: u64, name: &str, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_section(section, encoder),
None => Ok(())
}
}
fn render_field_inverse<'section, E>(&self, _: u64, name: &str, section: Section<'section>, encoder: &mut E) -> Result<(), E::Error>
where
E: Encoder,
{
match self.get(name) {
Some(v) => v.render_inverse(section, encoder),
None => Ok(())
}
}
}