<commit_before>use std::borrow::IntoCow;
use syntax::ast::{Expr, Ident, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use maud;

#[derive(Copy)]
pub enum Escape {
    PassThru,
    Escape,
}

pub struct Renderer<'cx, 's: 'cx> {
    pub cx: &'cx ExtCtxt<'s>,
    stmts: Vec<P<Stmt>>,
    w: Ident,
}

impl<'cx, 's> Renderer<'cx, 's> {
    /// Create a new `Renderer` using the given extension context.
    pub fn new(cx: &'cx ExtCtxt<'s>) -> Renderer<'cx, 's> {
        Renderer {
            cx: cx,
            stmts: vec![],
            w: Ident::new(token::intern("w")),
        }
    }

    /// Create a new `Renderer` under the same context as `self`.
    pub fn fork(&self) -> Renderer<'cx, 's> {
        Renderer {
            cx: self.cx,
            stmts: vec![],
            w: self.w,
        }
    }

    /// Reify the `Renderer` into a block of markup.
    pub fn into_expr(self) -> P<Expr> {
        let Renderer { cx, stmts, w } = self;
        quote_expr!(cx,
            ::maud::rt::make_markup(|$w: &mut ::std::fmt::Write| -> Result<(), ::std::fmt::Error> {
                $stmts
                Ok(())
            }))
    }

    /// Reify the `Renderer` into a raw list of statements.
    pub fn into_stmts(self) -> Vec<P<Stmt>> {
        let Renderer { stmts, .. } = self;
        stmts
    }

    /// Append the list of statements to the output.
    pub fn push_stmts(&mut self, mut stmts: Vec<P<Stmt>>) {
        self.stmts.append(&mut stmts);
    }

    /// Push an expression statement, also wrapping it with `try!`.
    fn push_try(&mut self, expr: P<Expr>) {
        let stmt = self.cx.stmt_expr(self.cx.expr_try(expr.span, expr));
        self.stmts.push(stmt);
    }

    /// Append a literal pre-escaped string.
    fn write(&mut self, s: &str) {
        let w = self.w;
        let expr = quote_expr!(self.cx, $w.write_str($s));
        self.push_try(expr);
    }

    /// Append a literal string, with the specified escaping method.
    pub fn string(&mut self, s: &str, escape: Escape) {
        let s = match escape {
            Escape::PassThru => s.into_cow(),
            Escape::Escape => maud::escape(s).into_cow(),
        };
        self.write(&s);
    }

    /// Append the result of an expression, with the specified escaping method.
    pub fn splice(&mut self, expr: P<Expr>, escape: Escape) {
        let w = self.w;
        let expr = match escape {
            Escape::PassThru =>
                quote_expr!(self.cx, ::maud::rt::write_fmt($w, $expr)),<commit_msg>Remove cow<commit_after>use syntax::ast::{Expr, Ident, Stmt};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::parse::token;
use syntax::ptr::P;

use maud;

#[derive(Copy)]
pub enum Escape {
    PassThru,
    Escape,
}

pub struct Renderer<'cx, 's: 'cx> {
    pub cx: &'cx ExtCtxt<'s>,
    stmts: Vec<P<Stmt>>,
    w: Ident,
}

impl<'cx, 's> Renderer<'cx, 's> {
    /// Create a new `Renderer` using the given extension context.
    pub fn new(cx: &'cx ExtCtxt<'s>) -> Renderer<'cx, 's> {
        Renderer {
            cx: cx,
            stmts: vec![],
            w: Ident::new(token::intern("w")),
        }
    }

    /// Create a new `Renderer` under the same context as `self`.
    pub fn fork(&self) -> Renderer<'cx, 's> {
        Renderer {
            cx: self.cx,
            stmts: vec![],
            w: self.w,
        }
    }

    /// Reify the `Renderer` into a block of markup.
    pub fn into_expr(self) -> P<Expr> {
        let Renderer { cx, stmts, w } = self;
        quote_expr!(cx,
            ::maud::rt::make_markup(|$w: &mut ::std::fmt::Write| -> Result<(), ::std::fmt::Error> {
                $stmts
                Ok(())
            }))
    }

    /// Reify the `Renderer` into a raw list of statements.
    pub fn into_stmts(self) -> Vec<P<Stmt>> {
        let Renderer { stmts, .. } = self;
        stmts
    }

    /// Append the list of statements to the output.
    pub fn push_stmts(&mut self, mut stmts: Vec<P<Stmt>>) {
        self.stmts.append(&mut stmts);
    }

    /// Push an expression statement, also wrapping it with `try!`.
    fn push_try(&mut self, expr: P<Expr>) {
        let stmt = self.cx.stmt_expr(self.cx.expr_try(expr.span, expr));
        self.stmts.push(stmt);
    }

    /// Append a literal pre-escaped string.
    fn write(&mut self, s: &str) {
        let w = self.w;
        let expr = quote_expr!(self.cx, $w.write_str($s));
        self.push_try(expr);
    }

    /// Append a literal string, with the specified escaping method.
    pub fn string(&mut self, s: &str, escape: Escape) {
        let escaped;
        let s = match escape {
            Escape::PassThru => s,
            Escape::Escape => { escaped = maud::escape(s); &*escaped },
        };
        self.write(s);
    }

    /// Append the result of an expression, with the specified escaping method.
    pub fn splice(&mut self, expr: P<Expr>, escape: Escape) {
        let w = self.w;
        let expr = match escape {
            Escape::PassThru =>
                quote_expr!(self.cx, ::maud::rt::write_fmt($w, $expr)),
{'fraction_non_alphanumeric': 0.1617703904136065, 'fraction_numerical': 0.0, 'mean_word_length': 2.093245666467424, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '740966', 'n_tokens_mistral': 1785, 'n_tokens_neox': 1775, 'n_words': 478}