linkerd2-proxy/codegen/src/lib.rs

1285 lines
28 KiB
Rust

extern crate ordermap;
use ordermap::OrderMap;
use std::fmt::{self, Write};
/// Defines a scope.
///
/// A scope contains modules, types, etc...
#[derive(Debug, Clone)]
pub struct Scope {
/// Scope documentation
docs: Option<Docs>,
/// Imports
imports: OrderMap<String, OrderMap<String, Import>>,
/// Contents of the documentation,
items: Vec<Item>,
}
#[derive(Debug, Clone)]
enum Item {
Module(Module),
Struct(Struct),
Enum(Enum),
Impl(Impl),
}
/// Defines a module
#[derive(Debug, Clone)]
pub struct Module {
/// Module name
name: String,
/// Visibility
vis: Option<String>,
/// Module documentation
docs: Option<Docs>,
/// Contents of the module
scope: Scope,
}
/// Defines an enumeration
#[derive(Debug, Clone)]
pub struct Enum {
type_def: TypeDef,
variants: Vec<Variant>,
}
/// Defines a struct
#[derive(Debug, Clone)]
pub struct Struct {
type_def: TypeDef,
/// Struct fields
fields: Fields,
}
#[derive(Debug, Clone)]
pub struct Type {
name: String,
generics: Vec<Type>,
}
/// A type definition
#[derive(Debug, Clone)]
struct TypeDef {
ty: Type,
vis: Option<String>,
docs: Option<Docs>,
derive: Vec<String>,
bounds: Vec<Field>,
}
/// An enum variant
#[derive(Debug, Clone)]
pub struct Variant {
name: String,
fields: Fields,
}
#[derive(Debug, Clone)]
enum Fields {
Empty,
Tuple(Vec<Type>),
Named(Vec<Field>),
}
/// Defines a struct field
#[derive(Debug, Clone)]
struct Field {
/// Field name
name: String,
/// Field type
ty: Type,
}
#[derive(Debug, Clone)]
pub struct Impl {
/// The struct being implemented
target: Type,
/// Impl level generics
generics: Vec<String>,
/// If implementing a trait
impl_trait: Option<String>,
/// Associated types
assoc_tys: Vec<Field>,
/// Bounds
bounds: Vec<Field>,
fns: Vec<Function>,
}
/// Import
#[derive(Debug, Clone)]
pub struct Import {
line: String,
vis: Option<String>,
}
/// A function definition
#[derive(Debug, Clone)]
pub struct Function {
/// Name of the function
name: String,
/// Function documentation
docs: Option<Docs>,
/// Function visibility
vis: Option<String>,
/// Function generics
generics: Vec<String>,
/// If the function takes `&self` or `&mut self`
arg_self: Option<String>,
/// Function arguments
args: Vec<Field>,
/// Return type
ret: Option<Type>,
/// Where bounds
bounds: Vec<Field>,
/// Body contents
body: Vec<Body>,
}
/// A block of code
#[derive(Debug, Clone)]
pub struct Block {
before: Option<String>,
after: Option<String>,
body: Vec<Body>,
}
#[derive(Debug, Clone)]
enum Body {
String(String),
Block(Block),
}
#[derive(Debug, Clone)]
struct Docs {
docs: String,
}
/// Formatting configuration
#[derive(Debug)]
pub struct Formatter<'a> {
/// Write destination
dst: &'a mut String,
/// Number of spaces to start a new line with
spaces: usize,
/// Number of spaces per indentiation
indent: usize,
}
const DEFAULT_INDENT: usize = 4;
// ===== impl Scope =====
impl Scope {
/// Returns a new scope
pub fn new() -> Self {
Scope {
docs: None,
imports: OrderMap::new(),
items: vec![],
}
}
/// Push an `use` line
pub fn import(&mut self, path: &str, ty: &str) -> &mut Import {
self.imports.entry(path.to_string())
.or_insert(OrderMap::new())
.entry(ty.to_string())
.or_insert_with(|| Import::new(path, ty))
}
/// Pushes a new module definition, returning a mutable reference to the
/// definition.
pub fn module(&mut self, name: &str) -> &mut Module {
self.push_module(Module::new(name));
match *self.items.last_mut().unwrap() {
Item::Module(ref mut v) => v,
_ => unreachable!(),
}
}
/// Push a module definition
pub fn push_module(&mut self, module: Module) -> &mut Self {
self.items.push(Item::Module(module));
self
}
/// Push a new struct definition, returning a mutable reference to the
/// definition.
pub fn structure(&mut self, name: &str) -> &mut Struct {
self.push_structure(Struct::new(name));
match *self.items.last_mut().unwrap() {
Item::Struct(ref mut v) => v,
_ => unreachable!(),
}
}
/// Push a structure definition
pub fn push_structure(&mut self, structure: Struct) -> &mut Self {
self.items.push(Item::Struct(structure));
self
}
/// Push a new struct definition, returning a mutable reference to the
/// definition.
pub fn enumeration(&mut self, name: &str) -> &mut Enum {
self.push_enumeration(Enum::new(name));
match *self.items.last_mut().unwrap() {
Item::Enum(ref mut v) => v,
_ => unreachable!(),
}
}
/// Push a structure definition
pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self {
self.items.push(Item::Enum(enumeration));
self
}
pub fn imp(&mut self, target: &str) -> &mut Impl {
self.push_imp(Impl::new(target));
match *self.items.last_mut().unwrap() {
Item::Impl(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_imp(&mut self, imp: Impl) -> &mut Self {
self.items.push(Item::Impl(imp));
self
}
/// Return a string representation of the scope.
pub fn to_string(&self) -> String {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
// Remove the trailing newline
if ret.as_bytes().last() == Some(&b'\n') {
ret.pop();
}
ret
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.fmt_imports(fmt)?;
if !self.imports.is_empty() {
write!(fmt, "\n")?;
}
for (i, item) in self.items.iter().enumerate() {
if i != 0 {
write!(fmt, "\n")?;
}
match *item {
Item::Module(ref v) => v.fmt(fmt)?,
Item::Struct(ref v) => v.fmt(fmt)?,
Item::Enum(ref v) => v.fmt(fmt)?,
Item::Impl(ref v) => v.fmt(fmt)?,
}
}
Ok(())
}
fn fmt_imports(&self, fmt: &mut Formatter) -> fmt::Result {
// First, collect all visibilities
let mut visibilities = vec![];
for (_, imports) in &self.imports {
for (_, import) in imports {
if !visibilities.contains(&import.vis) {
visibilities.push(import.vis.clone());
}
}
}
let mut tys = vec![];
// Loop over all visibilities and format the associated imports
for vis in &visibilities {
for (path, imports) in &self.imports {
tys.clear();
for (ty, import) in imports {
if *vis == import.vis {
tys.push(ty);
}
}
if !tys.is_empty() {
if let Some(ref vis) = *vis {
write!(fmt, "{} ", vis)?;
}
write!(fmt, "use {}::", path)?;
if tys.len() > 1 {
write!(fmt, "{{")?;
for (i, ty) in tys.iter().enumerate() {
if i != 0 { write!(fmt, ", ")?; }
write!(fmt, "{}", ty)?;
}
write!(fmt, "}};\n")?;
} else if tys.len() == 1 {
write!(fmt, "{};\n", tys[0])?;
}
}
}
}
Ok(())
}
}
// ===== impl Module =====
impl Module {
/// Return a new, blank module
pub fn new(name: &str) -> Self {
Module {
name: name.to_string(),
vis: None,
docs: None,
scope: Scope::new(),
}
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.vis = Some(vis.to_string());
self
}
/// Push an `use` line
pub fn import(&mut self, path: &str, ty: &str) -> &mut Self {
self.scope.import(path, ty);
self
}
/// Pushes a new module definition, returning a mutable reference to the
/// definition.
pub fn module(&mut self, name: &str) -> &mut Module {
self.scope.module(name)
}
/// Push a module definition
pub fn push_module(&mut self, module: Module) -> &mut Self {
self.scope.push_module(module);
self
}
/// Push a new struct definition, returning a mutable reference to the
/// definition.
pub fn structure(&mut self, name: &str) -> &mut Struct {
self.scope.structure(name)
}
/// Push a structure definition
pub fn push_structure(&mut self, structure: Struct) -> &mut Self {
self.scope.push_structure(structure);
self
}
/// Push a new struct definition, returning a mutable reference to the
/// definition.
pub fn enumeration(&mut self, name: &str) -> &mut Enum {
self.scope.enumeration(name)
}
/// Push a structure definition
pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self {
self.scope.push_enumeration(enumeration);
self
}
pub fn imp(&mut self, target: &str) -> &mut Impl {
self.scope.imp(target)
}
pub fn push_imp(&mut self, imp: Impl) -> &mut Self {
self.scope.push_imp(imp);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref vis) = self.vis {
write!(fmt, "{} ", vis)?;
}
write!(fmt, "mod {}", self.name)?;
fmt.block(|fmt| {
self.scope.fmt(fmt)
})
}
}
// ===== impl Struct =====
impl Struct {
/// Return a structure definition with the provided name
pub fn new(name: &str) -> Self {
Struct {
type_def: TypeDef::new(name),
fields: Fields::Empty,
}
}
/// Returns a reference to the type
pub fn ty(&self) -> &Type {
&self.type_def.ty
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.type_def.vis(vis);
self
}
pub fn generic(&mut self, name: &str) -> &mut Self {
self.type_def.ty.generic(name);
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.type_def.bound(name, ty);
self
}
pub fn doc(&mut self, docs: &str) -> &mut Self {
self.type_def.doc(docs);
self
}
pub fn derive(&mut self, name: &str) -> &mut Self {
self.type_def.derive(name);
self
}
pub fn field<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.fields.named(name, ty);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.type_def.fmt_head("struct", fmt)?;
self.fields.fmt(fmt)?;
Ok(())
}
}
// ===== impl Enum =====
impl Enum {
/// Return a structure definition with the provided name
pub fn new(name: &str) -> Self {
Enum {
type_def: TypeDef::new(name),
variants: vec![],
}
}
/// Returns a reference to the type
pub fn ty(&self) -> &Type {
&self.type_def.ty
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.type_def.vis(vis);
self
}
pub fn generic(&mut self, name: &str) -> &mut Self {
self.type_def.ty.generic(name);
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.type_def.bound(name, ty);
self
}
pub fn doc(&mut self, docs: &str) -> &mut Self {
self.type_def.doc(docs);
self
}
pub fn derive(&mut self, name: &str) -> &mut Self {
self.type_def.derive(name);
self
}
pub fn variant(&mut self, name: &str) -> &mut Variant {
self.push_variant(Variant::new(name));
self.variants.last_mut().unwrap()
}
pub fn push_variant(&mut self, variant: Variant) -> &mut Self {
self.variants.push(variant);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.type_def.fmt_head("enum", fmt)?;
fmt.block(|fmt| {
for variant in &self.variants {
variant.fmt(fmt)?;
}
Ok(())
})
}
}
// ===== impl Variant =====
impl Variant {
pub fn new(name: &str) -> Self {
Variant {
name: name.to_string(),
fields: Fields::Empty,
}
}
pub fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.fields.named(name, ty);
self
}
pub fn tuple(&mut self, ty: &str) -> &mut Self {
self.fields.tuple(ty);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{}", self.name)?;
self.fields.fmt(fmt)?;
write!(fmt, ",\n")?;
Ok(())
}
}
// ===== impl Type =====
impl Type {
pub fn new(name: &str) -> Self {
Type {
name: name.to_string(),
generics: vec![],
}
}
pub fn generic<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
// Make sure that the name doesn't already include generics
assert!(!self.name.contains("<"), "type name already includes generics");
self.generics.push(ty.into());
self
}
/// Rewrite the `Type` with the provided path
pub fn path(&self, path: &str) -> Type {
// TODO: This isn't really correct
assert!(!self.name.contains("::"));
let mut name = path.to_string();
name.push_str("::");
name.push_str(&self.name);
Type {
name,
generics: self.generics.clone(),
}
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{}", self.name)?;
Type::fmt_slice(&self.generics, fmt)
}
fn fmt_slice(generics: &[Type], fmt: &mut Formatter) -> fmt::Result {
if !generics.is_empty() {
write!(fmt, "<")?;
for (i, ty) in generics.iter().enumerate() {
if i != 0 { write!(fmt, ", ")? }
ty.fmt(fmt)?;
}
write!(fmt, ">")?;
}
Ok(())
}
}
impl<'a> From<&'a str> for Type {
fn from(src: &'a str) -> Self {
Type::new(src)
}
}
impl From<String> for Type {
fn from(src: String) -> Self {
Type {
name: src,
generics: vec![],
}
}
}
impl<'a> From<&'a String> for Type {
fn from(src: &'a String) -> Self {
Type::new(src)
}
}
impl<'a> From<&'a Type> for Type {
fn from(src: &'a Type) -> Self {
src.clone()
}
}
// ===== impl TypeDef =====
impl TypeDef {
/// Return a structure definition with the provided name
pub fn new(name: &str) -> Self {
TypeDef {
ty: Type::new(name),
vis: None,
docs: None,
derive: vec![],
bounds: vec![],
}
}
fn vis(&mut self, vis: &str) {
self.vis = Some(vis.to_string());
}
fn bound<T>(&mut self, name: &str, ty: T)
where T: Into<Type>,
{
self.bounds.push(Field {
name: name.to_string(),
ty: ty.into(),
});
}
fn doc(&mut self, docs: &str) {
self.docs = Some(Docs::new(docs));
}
fn derive(&mut self, name: &str) {
self.derive.push(name.to_string());
}
fn fmt_head(&self, keyword: &str, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref docs) = self.docs {
docs.fmt(fmt)?;
}
self.fmt_derive(fmt)?;
if let Some(ref vis) = self.vis {
write!(fmt, "{} ", vis)?;
}
write!(fmt, "{} ", keyword)?;
self.ty.fmt(fmt)?;
fmt_bounds(&self.bounds, fmt)?;
Ok(())
}
fn fmt_derive(&self, fmt: &mut Formatter) -> fmt::Result {
if !self.derive.is_empty() {
write!(fmt, "#[derive(")?;
for (i, name) in self.derive.iter().enumerate() {
if i != 0 { write!(fmt, ", ")? }
write!(fmt, "{}", name)?;
}
write!(fmt, ")]\n")?;
}
Ok(())
}
}
fn fmt_generics(generics: &[String], fmt: &mut Formatter) -> fmt::Result {
if !generics.is_empty() {
write!(fmt, "<")?;
for (i, ty) in generics.iter().enumerate() {
if i != 0 { write!(fmt, ", ")? }
write!(fmt, "{}", ty)?;
}
write!(fmt, ">")?;
}
Ok(())
}
fn fmt_bounds(bounds: &[Field], fmt: &mut Formatter) -> fmt::Result {
if !bounds.is_empty() {
write!(fmt, "\n")?;
// Write first bound
write!(fmt, "where {}: ", bounds[0].name)?;
bounds[0].ty.fmt(fmt)?;
write!(fmt, ",\n")?;
for bound in &bounds[1..] {
write!(fmt, " {}: ", bound.name)?;
bound.ty.fmt(fmt)?;
write!(fmt, ",\n")?;
}
}
Ok(())
}
// ===== impl Fields =====
impl Fields {
fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
match *self {
Fields::Empty => {
*self = Fields::Named(vec![Field {
name: name.to_string(),
ty: ty.into(),
}]);
}
Fields::Named(ref mut fields) => {
fields.push(Field {
name: name.to_string(),
ty: ty.into(),
});
}
_ => panic!("field list is named"),
}
self
}
fn tuple<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
match *self {
Fields::Empty => {
*self = Fields::Tuple(vec![ty.into()]);
}
Fields::Tuple(ref mut fields) => {
fields.push(ty.into());
}
_ => panic!("field list is tuple"),
}
self
}
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
match *self {
Fields::Named(ref fields) => {
assert!(!fields.is_empty());
fmt.block(|fmt| {
for f in fields {
write!(fmt, "{}: ", f.name)?;
f.ty.fmt(fmt)?;
write!(fmt, ",\n")?;
}
Ok(())
})?;
}
Fields::Tuple(ref tys) => {
assert!(!tys.is_empty());
write!(fmt, "(")?;
for (i, ty) in tys.iter().enumerate() {
if i != 0 { write!(fmt, ", ")?; }
ty.fmt(fmt)?;
}
write!(fmt, ")")?;
}
Fields::Empty => {}
}
Ok(())
}
}
// ===== impl Impl =====
impl Impl {
/// Return a new impl definition
pub fn new<T>(target: T) -> Self
where T: Into<Type>,
{
Impl {
target: target.into(),
generics: vec![],
impl_trait: None,
assoc_tys: vec![],
bounds: vec![],
fns: vec![],
}
}
pub fn generic(&mut self, name: &str) -> &mut Self {
self.generics.push(name.to_string());
self
}
pub fn target_generic<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.target.generic(ty);
self
}
pub fn impl_trait(&mut self, name: &str) -> &mut Self {
self.impl_trait = Some(name.to_string());
self
}
pub fn associate_type<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.assoc_tys.push(Field {
name: name.to_string(),
ty: ty.into(),
});
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.bounds.push(Field {
name: name.to_string(),
ty: ty.into(),
});
self
}
/// Define a new function
pub fn function(&mut self, name: &str) -> &mut Function {
self.push_function(Function::new(name));
self.fns.last_mut().unwrap()
}
/// Push a function definition
pub fn push_function(&mut self, func: Function) -> &mut Self {
self.fns.push(func);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "impl")?;
fmt_generics(&self.generics[..], fmt)?;
if let Some(ref t) = self.impl_trait {
write!(fmt, " {} for", t)?;
}
write!(fmt, " ")?;
self.target.fmt(fmt)?;
fmt_bounds(&self.bounds, fmt)?;
fmt.block(|fmt| {
// format associated types
if !self.assoc_tys.is_empty() {
for ty in &self.assoc_tys {
write!(fmt, "type {} = ", ty.name)?;
ty.ty.fmt(fmt)?;
write!(fmt, ";\n")?;
}
}
for (i, func) in self.fns.iter().enumerate() {
if i != 0 || !self.assoc_tys.is_empty() { write!(fmt, "\n")?; }
func.fmt(fmt)?;
}
Ok(())
})
}
}
// ===== impl Import =====
impl Import {
pub fn new(path: &str, ty: &str) -> Self {
Import {
line: format!("{}::{}", path, ty),
vis: None,
}
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.vis = Some(vis.to_string());
self
}
}
// ===== impl Func =====
impl Function {
pub fn new(name: &str) -> Self {
Function {
name: name.to_string(),
docs: None,
vis: None,
generics: vec![],
arg_self: None,
args: vec![],
ret: None,
bounds: vec![],
body: vec![],
}
}
pub fn docs(&mut self, docs: &str) -> &mut Self {
self.docs = Some(Docs::new(docs));
self
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.vis = Some(vis.to_string());
self
}
pub fn generic(&mut self, name: &str) -> &mut Self {
self.generics.push(name.to_string());
self
}
pub fn arg_self(&mut self) -> &mut Self {
self.arg_self = Some("self".to_string());
self
}
pub fn arg_ref_self(&mut self) -> &mut Self {
self.arg_self = Some("&self".to_string());
self
}
pub fn arg_mut_self(&mut self) -> &mut Self {
self.arg_self = Some("&mut self".to_string());
self
}
pub fn arg<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.args.push(Field {
name: name.to_string(),
ty: ty.into(),
});
self
}
pub fn ret<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.ret = Some(ty.into());
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.bounds.push(Field {
name: name.to_string(),
ty: ty.into(),
});
self
}
pub fn line<T>(&mut self, line: T) -> &mut Self
where T: ToString,
{
self.body.push(Body::String(line.to_string()));
self
}
pub fn block(&mut self, block: Block) -> &mut Self {
self.body.push(Body::Block(block));
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref docs) = self.docs {
docs.fmt(fmt)?;
}
if let Some(ref vis) = self.vis {
write!(fmt, "{} ", vis)?;
}
write!(fmt, "fn {}", self.name)?;
fmt_generics(&self.generics, fmt)?;
write!(fmt, "(")?;
if let Some(ref s) = self.arg_self {
write!(fmt, "{}", s)?;
}
for (i, arg) in self.args.iter().enumerate() {
if i != 0 || self.arg_self.is_some() {
write!(fmt, ", ")?;
}
write!(fmt, "{}: ", arg.name)?;
arg.ty.fmt(fmt)?;
}
write!(fmt, ")")?;
if let Some(ref ret) = self.ret {
write!(fmt, " -> ")?;
ret.fmt(fmt)?;
}
fmt_bounds(&self.bounds, fmt)?;
fmt.block(|fmt| {
for b in &self.body {
b.fmt(fmt)?;
}
Ok(())
})
}
}
// ===== impl Block =====
impl Block {
pub fn new(before: &str) -> Self {
Block {
before: Some(before.to_string()),
after: None,
body: vec![],
}
}
pub fn line<T>(&mut self, line: T) -> &mut Self
where T: ToString,
{
self.body.push(Body::String(line.to_string()));
self
}
pub fn block(&mut self, block: Block) -> &mut Self {
self.body.push(Body::Block(block));
self
}
pub fn after(&mut self, after: &str) -> &mut Self {
self.after = Some(after.to_string());
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref before) = self.before {
write!(fmt, "{}", before)?;
}
// Inlined `Formatter::fmt`
if !fmt.is_start_of_line() {
write!(fmt, " ")?;
}
write!(fmt, "{{\n")?;
fmt.indent(|fmt| {
for b in &self.body {
b.fmt(fmt)?;
}
Ok(())
})?;
write!(fmt, "}}")?;
if let Some(ref after) = self.after {
write!(fmt, "{}", after)?;
}
write!(fmt, "\n")?;
Ok(())
}
}
// ===== impl Body =====
impl Body {
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
match *self {
Body::String(ref s) => {
write!(fmt, "{}\n", s)
}
Body::Block(ref b) => {
b.fmt(fmt)
}
}
}
}
// ===== impl Docs =====
impl Docs {
fn new(docs: &str) -> Self {
Docs { docs: docs.to_string() }
}
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
for line in self.docs.lines() {
write!(fmt, "/// {}\n", line)?;
}
Ok(())
}
}
// ===== impl Formatter =====
impl<'a> Formatter<'a> {
pub fn new(dst: &'a mut String) -> Self {
Formatter {
dst,
spaces: 0,
indent: DEFAULT_INDENT,
}
}
fn block<F>(&mut self, f: F) -> fmt::Result
where F: FnOnce(&mut Self) -> fmt::Result
{
if !self.is_start_of_line() {
write!(self, " ")?;
}
write!(self, "{{\n")?;
self.indent(f)?;
write!(self, "}}\n")?;
Ok(())
}
/// Call the given function with the indentation level incremented by one.
fn indent<F, R>(&mut self, f: F) -> R
where F: FnOnce(&mut Self) -> R
{
self.spaces += self.indent;
let ret = f(self);
self.spaces -= self.indent;
ret
}
fn is_start_of_line(&self) -> bool {
self.dst.is_empty() ||
self.dst.as_bytes().last() == Some(&b'\n')
}
fn push_spaces(&mut self) {
for _ in 0..self.spaces {
self.dst.push_str(" ");
}
}
}
impl<'a> fmt::Write for Formatter<'a> {
fn write_str(&mut self, s: &str) -> fmt::Result {
let mut first = true;
let mut should_indent = self.is_start_of_line();
for line in s.lines() {
if !first {
self.dst.push_str("\n");
}
first = false;
let do_indent = should_indent &&
!line.is_empty() &&
line.as_bytes()[0] != b'\n';
if do_indent {
self.push_spaces();
}
// If this loops again, then we just wrote a new line
should_indent = true;
self.dst.push_str(line);
}
if s.as_bytes().last() == Some(&b'\n') {
self.dst.push_str("\n");
}
Ok(())
}
}