1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote};
use yarte_hir::HIR;
use crate::CodeGen;
pub struct FnFmtCodeGen<T: CodeGen> {
codegen: T,
parent: Ident,
}
impl<T: CodeGen> FnFmtCodeGen<T> {
pub fn new(codegen: T, parent: &'static str) -> FnFmtCodeGen<T> {
FnFmtCodeGen {
codegen,
parent: format_ident!("{}", parent),
}
}
fn body(&mut self, nodes: Vec<HIR>) -> (TokenStream, usize) {
let body = self.codegen.gen(nodes);
let size_hint = body.to_string().len();
(body, size_hint)
}
}
impl<T: CodeGen> CodeGen for FnFmtCodeGen<T> {
fn gen(&mut self, v: Vec<HIR>) -> TokenStream {
let (body, size_hint) = self.body(v);
let parent = &self.parent;
quote! {
{
#[allow(unused_imports)]
use std::fmt::{Write, Display};
#[allow(unused_imports)]
use #parent::*;
let mut buf = String::with_capacity(#size_hint);
let _ = write!(buf, "{}", #parent::DisplayFn::new(|_fmt| {
#body
Ok(())
}));
buf
}
}
}
}