Printing for attributes and types
diff --git a/src/attr.rs b/src/attr.rs
index 7b09b47..828006f 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -83,3 +83,41 @@
map!(word, MetaItem::Word)
));
}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use super::*;
+ use quote::{Tokens, ToTokens};
+
+ impl ToTokens for Attribute {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append("#[");
+ self.value.to_tokens(tokens);
+ tokens.append("]");
+ }
+ }
+
+ impl ToTokens for MetaItem {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ MetaItem::Word(ref ident) => tokens.append(&ident),
+ MetaItem::List(ref ident, ref inner) => {
+ tokens.append(&ident);
+ tokens.append("(");
+ for (i, meta_item) in inner.iter().enumerate() {
+ if i > 0 {
+ tokens.append(",");
+ }
+ meta_item.to_tokens(tokens);
+ }
+ tokens.append(")");
+ }
+ MetaItem::NameValue(ref name, ref value) => {
+ tokens.append(&name);
+ tokens.append("=");
+ value.to_tokens(tokens);
+ }
+ }
+ }
+ }
+}
diff --git a/src/generics.rs b/src/generics.rs
index 80738ae..51f56b9 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -101,7 +101,9 @@
named!(pub lifetime<&str, Lifetime>, preceded!(
punct!("'"),
- map!(word, |ident| Lifetime { ident: ident })
+ map!(word, |ident| Lifetime {
+ ident: format!("'{}", ident),
+ })
));
named!(pub lifetime_def<&str, LifetimeDef>, do_parse!(
@@ -173,3 +175,40 @@
)
));
}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use super::*;
+ use quote::{Tokens, ToTokens};
+
+ impl ToTokens for Lifetime {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.ident.to_tokens(tokens);
+ }
+ }
+
+ impl ToTokens for LifetimeDef {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.lifetime.to_tokens(tokens);
+ if !self.bounds.is_empty() {
+ tokens.append(":");
+ for (i, bound) in self.bounds.iter().enumerate() {
+ if i > 0 {
+ tokens.append("+");
+ }
+ bound.to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ impl ToTokens for TyParamBound {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ TyParamBound::MaybeSized => tokens.append("?Sized"),
+ TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
+ TyParamBound::Trait(ref trait_ref) => trait_ref.to_tokens(tokens),
+ }
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 397b9e1..cd7b545 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,9 @@
#[macro_use]
extern crate nom;
+#[cfg(feature = "printing")]
+extern crate quote;
+
#[macro_use]
mod do_parse;
diff --git a/src/ty.rs b/src/ty.rs
index cbc0bb1..3d1cb1d 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -410,3 +410,238 @@
})
));
}
+
+#[cfg(feature = "printing")]
+mod printing {
+ use super::*;
+ use quote::{Tokens, ToTokens};
+
+ impl ToTokens for Ty {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ Ty::Vec(ref inner) => {
+ tokens.append("[");
+ inner.to_tokens(tokens);
+ tokens.append("]");
+ }
+ Ty::FixedLengthVec(ref inner, len) => {
+ tokens.append("[");
+ inner.to_tokens(tokens);
+ tokens.append(";");
+ len.to_tokens(tokens);
+ tokens.append("]");
+ }
+ Ty::Ptr(ref target) => {
+ tokens.append("*");
+ match target.mutability {
+ Mutability::Mutable => tokens.append("mut"),
+ Mutability::Immutable => tokens.append("const"),
+ }
+ target.ty.to_tokens(tokens);
+ }
+ Ty::Rptr(ref lifetime, ref target) => {
+ tokens.append("&");
+ lifetime.to_tokens(tokens);
+ if let Mutability::Mutable = target.mutability {
+ tokens.append("mut");
+ }
+ target.ty.to_tokens(tokens);
+ }
+ Ty::BareFn(ref func) => {
+ func.to_tokens(tokens);
+ }
+ Ty::Never => {
+ tokens.append("!");
+ }
+ Ty::Tup(ref elems) => {
+ tokens.append("(");
+ for (i, elem) in elems.iter().enumerate() {
+ if i > 0 {
+ tokens.append(",");
+ }
+ elem.to_tokens(tokens);
+ }
+ if elems.len() == 1 {
+ tokens.append(",");
+ }
+ tokens.append(")");
+ }
+ Ty::Path(ref qself, ref path) => {
+ match *qself {
+ Some(ref qself) => {
+ tokens.append("<");
+ qself.ty.to_tokens(tokens);
+ if qself.position > 0 {
+ tokens.append("as");
+ for (i, segment) in path.segments.iter()
+ .take(qself.position)
+ .enumerate()
+ {
+ if i > 0 || path.global {
+ tokens.append("::");
+ }
+ segment.to_tokens(tokens);
+ }
+ for segment in path.segments.iter()
+ .skip(qself.position)
+ {
+ tokens.append("::");
+ segment.to_tokens(tokens);
+ }
+ }
+ tokens.append(">");
+ }
+ None => path.to_tokens(tokens),
+ }
+ }
+ Ty::ObjectSum(_, _) => unimplemented!(),
+ Ty::PolyTraitRef(_) => unimplemented!(),
+ Ty::ImplTrait(ref bounds) => {
+ tokens.append("impl");
+ for (i, bound) in bounds.iter().enumerate() {
+ if i > 0 {
+ tokens.append("+");
+ }
+ bound.to_tokens(tokens);
+ }
+ }
+ Ty::Paren(ref inner) => {
+ tokens.append("(");
+ inner.to_tokens(tokens);
+ tokens.append(")");
+ }
+ Ty::Infer => {
+ tokens.append("_");
+ }
+ }
+ }
+ }
+
+ impl ToTokens for Path {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ for (i, segment) in self.segments.iter().enumerate() {
+ if i > 0 || self.global {
+ tokens.append("::");
+ }
+ segment.to_tokens(tokens);
+ }
+ }
+ }
+
+ impl ToTokens for PathSegment {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.ident.to_tokens(tokens);
+ self.parameters.to_tokens(tokens);
+ }
+ }
+
+ impl ToTokens for PathParameters {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ match *self {
+ PathParameters::AngleBracketed(ref parameters) => {
+ parameters.to_tokens(tokens);
+ }
+ PathParameters::Parenthesized(ref parameters) => {
+ parameters.to_tokens(tokens);
+ }
+ }
+ }
+ }
+
+ impl ToTokens for AngleBracketedParameterData {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ let has_lifetimes = !self.lifetimes.is_empty();
+ let has_types = !self.types.is_empty();
+ let has_bindings = !self.bindings.is_empty();
+ if !has_lifetimes && !has_types && !has_bindings {
+ return;
+ }
+
+ tokens.append("<");
+
+ let mut first = true;
+ for lifetime in &self.lifetimes {
+ if !first {
+ tokens.append(",");
+ }
+ lifetime.to_tokens(tokens);
+ first = false;
+ }
+ for ty in &self.types {
+ if !first {
+ tokens.append(",");
+ }
+ ty.to_tokens(tokens);
+ first = false;
+ }
+ for binding in &self.bindings {
+ if !first {
+ tokens.append(",");
+ }
+ binding.to_tokens(tokens);
+ first = false;
+ }
+
+ tokens.append(">");
+ }
+ }
+
+ impl ToTokens for TypeBinding {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ self.ident.to_tokens(tokens);
+ tokens.append("=");
+ self.ty.to_tokens(tokens);
+ }
+ }
+
+ impl ToTokens for ParenthesizedParameterData {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append("(");
+ for (i, input) in self.inputs.iter().enumerate() {
+ if i > 0 {
+ tokens.append(",");
+ }
+ input.to_tokens(tokens);
+ }
+ tokens.append(")");
+ if let Some(ref output) = self.output {
+ tokens.append("->");
+ output.to_tokens(tokens);
+ }
+ }
+ }
+
+ impl ToTokens for PolyTraitRef {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ if !self.bound_lifetimes.is_empty() {
+ tokens.append("<");
+ for (i, lifetime) in self.bound_lifetimes.iter().enumerate() {
+ if i > 0 {
+ tokens.append(",");
+ }
+ lifetime.to_tokens(tokens);
+ }
+ tokens.append(">");
+ }
+ self.trait_ref.to_tokens(tokens);
+ }
+ }
+
+ impl ToTokens for BareFnTy {
+ fn to_tokens(&self, tokens: &mut Tokens) {
+ tokens.append("fn");
+ if !self.lifetimes.is_empty() {
+ tokens.append("<");
+ for (i, lifetime) in self.lifetimes.iter().enumerate() {
+ if i > 0 {
+ tokens.append(",");
+ }
+ lifetime.to_tokens(tokens);
+ }
+ tokens.append(">");
+ }
+ tokens.append("(");
+ tokens.append(")");
+ }
+ }
+}