mirror of
https://gitee.com/openharmony/third_party_rust_syn
synced 2024-11-23 07:50:04 +00:00
Round trip testing
This commit is contained in:
parent
590cdfd074
commit
4a51dc70fc
@ -20,3 +20,8 @@ visit = []
|
||||
clippy = { version = "0.*", optional = true }
|
||||
quote = { version = "0.2", optional = true }
|
||||
unicode-xid = { version = "0.0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
syntex_pos = "0.44.0"
|
||||
syntex_syntax = "0.44.0"
|
||||
walkdir = "0.1.8"
|
||||
|
58
src/attr.rs
58
src/attr.rs
@ -1,12 +1,24 @@
|
||||
use super::*;
|
||||
|
||||
use std::iter;
|
||||
|
||||
/// Doc-comments are promoted to attributes that have `is_sugared_doc` = true
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Attribute {
|
||||
pub style: AttrStyle,
|
||||
pub value: MetaItem,
|
||||
pub is_sugared_doc: bool,
|
||||
}
|
||||
|
||||
/// Distinguishes between Attributes that decorate items and Attributes that
|
||||
/// are contained as statements within items. These two cases need to be
|
||||
/// distinguished for pretty-printing.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum AttrStyle {
|
||||
Outer,
|
||||
Inner,
|
||||
}
|
||||
|
||||
/// A compile-time attribute item.
|
||||
///
|
||||
/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
|
||||
@ -36,6 +48,31 @@ impl MetaItem {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait FilterAttrs<'a> {
|
||||
type Ret: Iterator<Item = &'a Attribute>;
|
||||
|
||||
fn outer(self) -> Self::Ret;
|
||||
fn inner(self) -> Self::Ret;
|
||||
}
|
||||
|
||||
impl<'a, T> FilterAttrs<'a> for T where T: IntoIterator<Item = &'a Attribute> {
|
||||
type Ret = iter::Filter<T::IntoIter, fn(&&Attribute) -> bool>;
|
||||
|
||||
fn outer(self) -> Self::Ret {
|
||||
fn is_outer(attr: &&Attribute) -> bool {
|
||||
attr.style == AttrStyle::Outer
|
||||
}
|
||||
self.into_iter().filter(is_outer)
|
||||
}
|
||||
|
||||
fn inner(self) -> Self::Ret {
|
||||
fn is_inner(attr: &&Attribute) -> bool {
|
||||
attr.style == AttrStyle::Inner
|
||||
}
|
||||
self.into_iter().filter(is_inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
@ -43,13 +80,27 @@ pub mod parsing {
|
||||
use lit::{Lit, StrStyle};
|
||||
use lit::parsing::lit;
|
||||
|
||||
named!(pub attribute -> Attribute, alt!(
|
||||
named!(pub inner_attr -> Attribute, do_parse!(
|
||||
punct!("#") >>
|
||||
punct!("!") >>
|
||||
punct!("[") >>
|
||||
meta_item: meta_item >>
|
||||
punct!("]") >>
|
||||
(Attribute {
|
||||
style: AttrStyle::Inner,
|
||||
value: meta_item,
|
||||
is_sugared_doc: false,
|
||||
})
|
||||
));
|
||||
|
||||
named!(pub outer_attr -> Attribute, alt!(
|
||||
do_parse!(
|
||||
punct!("#") >>
|
||||
punct!("[") >>
|
||||
meta_item: meta_item >>
|
||||
punct!("]") >>
|
||||
(Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: meta_item,
|
||||
is_sugared_doc: false,
|
||||
})
|
||||
@ -60,6 +111,7 @@ pub mod parsing {
|
||||
not!(peek!(tag!("/"))) >>
|
||||
content: take_until!("\n") >>
|
||||
(Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: MetaItem::NameValue(
|
||||
"doc".into(),
|
||||
Lit::Str(
|
||||
@ -102,6 +154,7 @@ mod printing {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
match *self {
|
||||
Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: MetaItem::NameValue(
|
||||
ref name,
|
||||
Lit::Str(ref value, StrStyle::Cooked),
|
||||
@ -112,6 +165,9 @@ mod printing {
|
||||
}
|
||||
_ => {
|
||||
tokens.append("#");
|
||||
if let AttrStyle::Inner = self.style {
|
||||
tokens.append("!");
|
||||
}
|
||||
tokens.append("[");
|
||||
self.value.to_tokens(tokens);
|
||||
tokens.append("]");
|
||||
|
@ -49,7 +49,7 @@ pub struct Discriminant {
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use attr::parsing::attribute;
|
||||
use attr::parsing::outer_attr;
|
||||
use ident::parsing::ident;
|
||||
use lit::parsing::int;
|
||||
use ty::parsing::ty;
|
||||
@ -71,7 +71,7 @@ pub mod parsing {
|
||||
));
|
||||
|
||||
named!(variant -> Variant, do_parse!(
|
||||
attrs: many0!(attribute) >>
|
||||
attrs: many0!(outer_attr) >>
|
||||
id: ident >>
|
||||
data: alt!(
|
||||
struct_like_body => { VariantData::Struct }
|
||||
@ -106,7 +106,7 @@ pub mod parsing {
|
||||
));
|
||||
|
||||
named!(struct_field -> Field, do_parse!(
|
||||
attrs: many0!(attribute) >>
|
||||
attrs: many0!(outer_attr) >>
|
||||
vis: visibility >>
|
||||
id: ident >>
|
||||
punct!(":") >>
|
||||
@ -120,7 +120,7 @@ pub mod parsing {
|
||||
));
|
||||
|
||||
named!(tuple_field -> Field, do_parse!(
|
||||
attrs: many0!(attribute) >>
|
||||
attrs: many0!(outer_attr) >>
|
||||
vis: visibility >>
|
||||
ty: ty >>
|
||||
(Field {
|
||||
|
74
src/item.rs
74
src/item.rs
@ -209,7 +209,7 @@ pub struct MethodSig {
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use attr::parsing::attribute;
|
||||
use attr::parsing::outer_attr;
|
||||
use data::parsing::visibility;
|
||||
use ident::parsing::ident;
|
||||
use macro_input::{Body, MacroInput};
|
||||
@ -234,7 +234,7 @@ pub mod parsing {
|
||||
));
|
||||
|
||||
named!(item_extern_crate -> Item, do_parse!(
|
||||
attrs: many0!(attribute) >>
|
||||
attrs: many0!(outer_attr) >>
|
||||
vis: visibility >>
|
||||
keyword!("extern") >>
|
||||
keyword!("crate") >>
|
||||
@ -275,3 +275,73 @@ pub mod parsing {
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use attr::FilterAttrs;
|
||||
use data::{VariantData, Visibility};
|
||||
use quote::{Tokens, ToTokens};
|
||||
|
||||
impl ToTokens for Item {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
for attr in self.attrs.outer() {
|
||||
attr.to_tokens(tokens);
|
||||
}
|
||||
match self.node {
|
||||
ItemKind::ExternCrate(ref original) => {
|
||||
tokens.append("extern");
|
||||
tokens.append("crate");
|
||||
if let Some(ref original) = *original {
|
||||
original.to_tokens(tokens);
|
||||
tokens.append("as");
|
||||
}
|
||||
self.ident.to_tokens(tokens);
|
||||
tokens.append(";");
|
||||
}
|
||||
ItemKind::Use(ref _view_path) => unimplemented!(),
|
||||
ItemKind::Static(ref _ty, ref _mutability, ref _expr) => unimplemented!(),
|
||||
ItemKind::Const(ref _ty, ref _expr) => unimplemented!(),
|
||||
ItemKind::Fn(ref _decl, _unsafety, _constness, ref _abi, ref _generics, ref _block) => unimplemented!(),
|
||||
ItemKind::Mod(ref _items) => unimplemented!(),
|
||||
ItemKind::ForeignMod(ref _foreign_mod) => unimplemented!(),
|
||||
ItemKind::Ty(ref _ty, ref _generics) => unimplemented!(),
|
||||
ItemKind::Enum(ref variants, ref generics) => {
|
||||
if let Visibility::Public = self.vis {
|
||||
tokens.append("pub");
|
||||
}
|
||||
tokens.append("enum");
|
||||
self.ident.to_tokens(tokens);
|
||||
generics.to_tokens(tokens);
|
||||
generics.where_clause.to_tokens(tokens);
|
||||
tokens.append("{");
|
||||
for variant in variants {
|
||||
variant.to_tokens(tokens);
|
||||
tokens.append(",");
|
||||
}
|
||||
tokens.append("}");
|
||||
}
|
||||
ItemKind::Struct(ref variant_data, ref generics) => {
|
||||
if let Visibility::Public = self.vis {
|
||||
tokens.append("pub");
|
||||
}
|
||||
tokens.append("struct");
|
||||
self.ident.to_tokens(tokens);
|
||||
generics.to_tokens(tokens);
|
||||
generics.where_clause.to_tokens(tokens);
|
||||
variant_data.to_tokens(tokens);
|
||||
match *variant_data {
|
||||
VariantData::Struct(_) => { /* no semicolon */ }
|
||||
VariantData::Tuple(_) |
|
||||
VariantData::Unit => tokens.append(";"),
|
||||
}
|
||||
}
|
||||
ItemKind::Union(ref _variant_data, ref _generics) => unimplemented!(),
|
||||
ItemKind::Trait(_unsafety, ref _generics, ref _bound, ref _item) => unimplemented!(),
|
||||
ItemKind::DefaultImpl(_unsafety, ref _path) => unimplemented!(),
|
||||
ItemKind::Impl(_unsafety, _polarity, ref _generics, ref _path, ref _ty, ref _item) => unimplemented!(),
|
||||
ItemKind::Mac(ref _mac) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
43
src/krate.rs
Normal file
43
src/krate.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Crate {
|
||||
attrs: Vec<Attribute>,
|
||||
items: Vec<Item>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use attr::parsing::inner_attr;
|
||||
use item::parsing::item;
|
||||
use nom::multispace;
|
||||
|
||||
named!(pub krate -> Crate, do_parse!(
|
||||
attrs: many0!(inner_attr) >>
|
||||
items: many0!(item) >>
|
||||
option!(multispace) >>
|
||||
(Crate {
|
||||
attrs: attrs,
|
||||
items: items,
|
||||
})
|
||||
));
|
||||
}
|
||||
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use attr::FilterAttrs;
|
||||
use quote::{Tokens, ToTokens};
|
||||
|
||||
impl ToTokens for Crate {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
for attr in self.attrs.inner() {
|
||||
attr.to_tokens(tokens);
|
||||
}
|
||||
for item in &self.items {
|
||||
item.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/lib.rs
13
src/lib.rs
@ -19,6 +19,7 @@ mod escape;
|
||||
mod attr;
|
||||
pub use attr::{
|
||||
Attribute,
|
||||
AttrStyle,
|
||||
MetaItem,
|
||||
};
|
||||
|
||||
@ -65,6 +66,11 @@ pub use generics::{
|
||||
WhereRegionPredicate,
|
||||
};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
mod krate;
|
||||
#[cfg(feature = "full")]
|
||||
pub use krate::Crate;
|
||||
|
||||
mod ident;
|
||||
pub use ident::{
|
||||
Ident,
|
||||
@ -155,12 +161,17 @@ mod parsing {
|
||||
use nom;
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
use {expr, item};
|
||||
use {expr, item, krate};
|
||||
|
||||
pub fn parse_macro_input(input: &str) -> Result<MacroInput, String> {
|
||||
unwrap("macro input", macro_input::parsing::macro_input, input)
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
pub fn parse_crate(input: &str) -> Result<Crate, String> {
|
||||
unwrap("crate", krate::parsing::krate, input)
|
||||
}
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
pub fn parse_item(input: &str) -> Result<Item, String> {
|
||||
unwrap("item", item::parsing::item, input)
|
||||
|
@ -18,14 +18,14 @@ pub enum Body {
|
||||
#[cfg(feature = "parsing")]
|
||||
pub mod parsing {
|
||||
use super::*;
|
||||
use attr::parsing::attribute;
|
||||
use attr::parsing::outer_attr;
|
||||
use data::parsing::{visibility, struct_body, enum_body};
|
||||
use generics::parsing::generics;
|
||||
use ident::parsing::ident;
|
||||
use nom::multispace;
|
||||
|
||||
named!(pub macro_input -> MacroInput, do_parse!(
|
||||
attrs: many0!(attribute) >>
|
||||
attrs: many0!(outer_attr) >>
|
||||
vis: visibility >>
|
||||
which: alt!(keyword!("struct") | keyword!("enum")) >>
|
||||
id: ident >>
|
||||
@ -55,12 +55,13 @@ pub mod parsing {
|
||||
#[cfg(feature = "printing")]
|
||||
mod printing {
|
||||
use super::*;
|
||||
use attr::FilterAttrs;
|
||||
use data::{Visibility, VariantData};
|
||||
use quote::{Tokens, ToTokens};
|
||||
|
||||
impl ToTokens for MacroInput {
|
||||
fn to_tokens(&self, tokens: &mut Tokens) {
|
||||
for attr in &self.attrs {
|
||||
for attr in self.attrs.outer() {
|
||||
attr.to_tokens(tokens);
|
||||
}
|
||||
if let Visibility::Public = self.vis {
|
||||
|
529
tests/cases/structs_enums.rs
Normal file
529
tests/cases/structs_enums.rs
Normal file
@ -0,0 +1,529 @@
|
||||
#![feature(rustc_macro)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultStruct<A, B, C, D, E> where C: MyDefault, E: MyDefault {
|
||||
a1: A,
|
||||
#[serde(default)]
|
||||
a2: B,
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a3: C,
|
||||
#[serde(skip_deserializing)]
|
||||
a4: D,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
a5: E,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum DefaultEnum<A, B, C, D, E> where C: MyDefault, E: MyDefault {
|
||||
Struct {
|
||||
a1: A,
|
||||
#[serde(default)]
|
||||
a2: B,
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a3: C,
|
||||
#[serde(skip_deserializing)]
|
||||
a4: D,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
a5: E,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NoStdDefault(i8);
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ContainsNoStdDefault<A: MyDefault> {
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a: A,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ContainsNotDeserialize<A, B, C: DeserializeWith, E: MyDefault> {
|
||||
#[serde(skip_deserializing)]
|
||||
a: A,
|
||||
#[serde(skip_deserializing, default)]
|
||||
b: B,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with", default)]
|
||||
c: C,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
e: E,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[derive(Deserialize)]
|
||||
struct DenyUnknown {
|
||||
a1: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename = "Superhero")]
|
||||
#[derive(Deserialize)]
|
||||
struct RenameStruct {
|
||||
a1: i32,
|
||||
#[serde(rename = "a3")]
|
||||
a2: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))]
|
||||
#[derive(Deserialize)]
|
||||
struct RenameStructSerializeDeserialize {
|
||||
a1: i32,
|
||||
#[serde(rename(serialize = "a4", deserialize = "a5"))]
|
||||
a2: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename = "Superhero")]
|
||||
#[derive(Deserialize)]
|
||||
enum RenameEnum {
|
||||
|
||||
#[serde(rename = "bruce_wayne")]
|
||||
Batman ,
|
||||
|
||||
#[serde(rename = "clark_kent")]
|
||||
Superman ( i8 ) ,
|
||||
|
||||
#[serde(rename = "diana_prince")]
|
||||
WonderWoman ( i8 , i8 ) ,
|
||||
|
||||
#[serde(rename = "barry_allan")]
|
||||
Flash {
|
||||
#[serde(rename = "b")]
|
||||
a : i32,
|
||||
} ,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[serde ( rename ( serialize = "SuperheroSer" , deserialize = "SuperheroDe" ) ) ]
|
||||
#[derive(Serialize)]
|
||||
enum RenameEnumSerializeDeserialize<A> {
|
||||
|
||||
#[serde(rename(serialize = "dick_grayson", deserialize = "jason_todd"))]
|
||||
Robin {
|
||||
a: i8,
|
||||
#[serde(rename(serialize = "c"))]
|
||||
#[serde(rename(deserialize = "d"))]
|
||||
b: A,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SkipSerializingStruct< 'a , B, C> where C : ShouldSkip {
|
||||
a: & 'a i8,
|
||||
#[serde(skip_serializing)]
|
||||
b: B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
|
||||
c: C,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip {
|
||||
Struct {
|
||||
a: &'a i8,
|
||||
#[serde(skip_serializing)]
|
||||
_b: B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
|
||||
c: C,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ContainsNotSerialize<'a, B, C, D> where B: 'a , D: SerializeWith {
|
||||
a: &'a Option<i8>,
|
||||
#[serde(skip_serializing)]
|
||||
b: &'a B,
|
||||
#[serde(skip_serializing)]
|
||||
c: Option<C>,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
d: D,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SerializeWithStruct<'a, B> where B: SerializeWith {
|
||||
a: &'a i8,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
b: B,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum SerializeWithEnum<'a, B> where B: SerializeWith {
|
||||
Struct {
|
||||
a: &'a i8,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
b: B,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DeserializeWithStruct<B> where B: DeserializeWith {
|
||||
a: i8,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
b: B,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum DeserializeWithEnum<B> where B: DeserializeWith {
|
||||
Struct {
|
||||
a: i8,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
b: B,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum InvalidLengthEnum {
|
||||
A(i32, i32, i32),
|
||||
B(
|
||||
#[serde(skip_deserializing)]
|
||||
i32, i32, i32),
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct TupleStruct(i32, i32, i32);
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
c: i32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
enum Enum {
|
||||
Unit,
|
||||
Simple(i32),
|
||||
Seq(i32, i32, i32),
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct IgnoreBase {
|
||||
a: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct With<T> {
|
||||
t: T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct WithRef<'a, T: 'a> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: Option<&'a T>,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct PhantomX {
|
||||
x: PhantomData<X>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct PhantomT<T> {
|
||||
t: PhantomData<T>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct NoBounds<T> {
|
||||
t: T,
|
||||
option: Option<T>,
|
||||
boxed: Box<T>,
|
||||
option_boxed: Option<Box<T>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum EnumWith<T> {
|
||||
Unit,
|
||||
Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X),
|
||||
Tuple(T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X),
|
||||
Struct {
|
||||
t: T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
|
||||
t: T,
|
||||
rrrt: &'a &'b &'c T,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X);
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Tuple<T>(T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X);
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum TreeNode<D> {
|
||||
Split {
|
||||
left: Box<TreeNode<D>>,
|
||||
right: Box<TreeNode<D>>,
|
||||
},
|
||||
Leaf {
|
||||
data: D,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct ListNode<D> {
|
||||
data: D,
|
||||
next: Box<ListNode<D>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct RecursiveA {
|
||||
b: Box<RecursiveB>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum RecursiveB { A(RecursiveA), }
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct RecursiveGenericA<T> {
|
||||
t: T,
|
||||
b: Box<RecursiveGenericB<T>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum RecursiveGenericB<T> { T(T), A(RecursiveGenericA<T>), }
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct OptionStatic<'a> {
|
||||
a: Option<&'a str>,
|
||||
b: Option<&'static str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound = "D: SerializeWith + DeserializeWith")]
|
||||
#[derive(Deserialize)]
|
||||
struct WithTraits1<D, E> {
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound = "E: SerializeWith + DeserializeWith")]
|
||||
e: E,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound(serialize = "D: SerializeWith",
|
||||
deserialize = "D: DeserializeWith"))]
|
||||
#[derive(Deserialize)]
|
||||
struct WithTraits2<D, E> {
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
bound(serialize = "E: SerializeWith"))]
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound(deserialize = "E: DeserializeWith"))]
|
||||
e: E,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct CowStr<'a>(Cow<'a, str>);
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound(deserialize = "T::Owned: Deserialize"))]
|
||||
#[derive(Deserialize)]
|
||||
struct CowT < 'a , T : ? Sized + 'a + ToOwned > ( Cow < 'a , T > ) ;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DeNamedTuple<A, B, C>(A, B, C);
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
|
||||
a: &'a A,
|
||||
b: &'b mut B,
|
||||
c: C,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DeNamedMap<A, B, C> {
|
||||
a: A,
|
||||
b: < Vec < T > as a :: b :: Trait > :: AssociatedItem,
|
||||
c: < Vec < T > > :: AssociatedItem,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum SerEnum<'a, B: 'a, C: 'a, D> where for < 'a > D: 'a {
|
||||
Unit,
|
||||
Seq(i8, B, &'a C, &'a mut D),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: &'a C,
|
||||
d: &'a mut D,
|
||||
},
|
||||
_Unit2,
|
||||
_Seq2(i8, B, &'a C, &'a mut D),
|
||||
_Map2 {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: &'a C,
|
||||
d: &'a mut D,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum DeEnum<B, C, D> {
|
||||
Unit,
|
||||
Seq(i8, B, C, D),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
},
|
||||
_Unit2,
|
||||
_Seq2(i8, B, C, D),
|
||||
_Map2 {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum Lifetimes<'a> {
|
||||
LifetimeSeq(&'a i32),
|
||||
NoLifetimeSeq(i32),
|
||||
LifetimeMap {
|
||||
a: &'a i32,
|
||||
},
|
||||
NoLifetimeMap {
|
||||
a: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericStruct<T> {
|
||||
x: T,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericNewTypeStruct<T>(T);
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericTupleStruct<T, U>(T, U);
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub enum GenericEnum<T, U: for < 'a > F<'a>> {
|
||||
Unit,
|
||||
NewType(T),
|
||||
Seq(T, U),
|
||||
Map {
|
||||
x: T,
|
||||
y: U,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
||||
phantom: std :: marker :: PhantomData<T>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct UnitStruct;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TupleStruct(i32, i32, i32);
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
enum Enum {
|
||||
Unit,
|
||||
One(i32),
|
||||
Seq(i32, i32),
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Bounds<T: Serialize + Deserialize> {
|
||||
t: T,
|
||||
option: Option<T>,
|
||||
boxed: Box<T>,
|
||||
option_boxed: Option<Box<T>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[rustc_copy_clone_marker]
|
||||
struct UnitStruct;
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[allow(dead_code)]
|
||||
#[deny(unused_variables)]
|
||||
enum Void { }
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct NamedUnit;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[doc = r" A custom basic event not covered by the Matrix specification."]
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CustomEvent {
|
||||
/// The event's content.
|
||||
content: String,
|
||||
}
|
@ -38,6 +38,7 @@ fn test_struct() {
|
||||
vis: Visibility::Public,
|
||||
attrs: vec![
|
||||
Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: MetaItem::List("derive".into(), vec![
|
||||
MetaItem::Word("Debug".into()),
|
||||
MetaItem::Word("Clone".into()),
|
||||
@ -96,6 +97,7 @@ fn test_enum() {
|
||||
vis: Visibility::Public,
|
||||
attrs: vec![
|
||||
Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: MetaItem::NameValue(
|
||||
"doc".into(),
|
||||
Lit::Str(
|
||||
@ -106,6 +108,7 @@ fn test_enum() {
|
||||
is_sugared_doc: true,
|
||||
},
|
||||
Attribute {
|
||||
style: AttrStyle::Outer,
|
||||
value: MetaItem::Word("must_use".into()),
|
||||
is_sugared_doc: false,
|
||||
},
|
||||
|
107
tests/test_round_trip.rs
Normal file
107
tests/test_round_trip.rs
Normal file
@ -0,0 +1,107 @@
|
||||
#![cfg(feature = "full")]
|
||||
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
extern crate syn;
|
||||
extern crate syntex_pos;
|
||||
extern crate syntex_syntax;
|
||||
extern crate walkdir;
|
||||
|
||||
use syntex_pos::Span;
|
||||
use syntex_syntax::ast::{self, Attribute, TyParam};
|
||||
use syntex_syntax::fold::{self, Folder};
|
||||
use syntex_syntax::parse::{self, ParseSess, PResult};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
macro_rules! errorf {
|
||||
($($tt:tt)*) => {
|
||||
write!(io::stderr(), $($tt)*).unwrap();
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round_trip() {
|
||||
let mut success = true;
|
||||
|
||||
for entry in walkdir::WalkDir::new("tests/cases").into_iter() {
|
||||
let entry = entry.unwrap();
|
||||
|
||||
let path = entry.path();
|
||||
if path.extension().map(|e| e != "rs").unwrap_or(true) {
|
||||
continue;
|
||||
}
|
||||
errorf!("=== {}: ", path.display());
|
||||
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut content = String::new();
|
||||
file.read_to_string(&mut content).unwrap();
|
||||
|
||||
let krate = match syn::parse_crate(&content) {
|
||||
Ok(krate) => krate,
|
||||
Err(msg) => {
|
||||
errorf!("syn failed to parse\n{}\n", msg);
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let back = quote!(#krate).to_string();
|
||||
|
||||
let sess = ParseSess::new();
|
||||
let before = syntex_parse(content, &sess).unwrap();
|
||||
let after = match syntex_parse(back, &sess) {
|
||||
Ok(after) => after,
|
||||
Err(mut diagnostic) => {
|
||||
errorf!("syntex failed to parse");
|
||||
diagnostic.emit();
|
||||
success = false;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if before == after {
|
||||
errorf!("pass\n");
|
||||
} else {
|
||||
errorf!("FAIL\nbefore: {:?}\nafter: {:?}\n", before, after);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
assert!(success);
|
||||
}
|
||||
|
||||
fn syntex_parse<'a>(content: String, sess: &'a ParseSess) -> PResult<'a, ast::Crate> {
|
||||
let name = "test_round_trip".to_string();
|
||||
let cfg = Vec::new();
|
||||
parse::parse_crate_from_source_str(name, content, cfg, sess).map(respan_crate)
|
||||
}
|
||||
|
||||
fn respan_crate(krate: ast::Crate) -> ast::Crate {
|
||||
struct Respanner;
|
||||
|
||||
impl Folder for Respanner {
|
||||
fn new_span(&mut self, _: Span) -> Span {
|
||||
syntex_pos::DUMMY_SP
|
||||
}
|
||||
|
||||
fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
|
||||
TyParam {
|
||||
// default fold_ty_param does not fold the span
|
||||
span: self.new_span(tp.span),
|
||||
.. fold::noop_fold_ty_param(tp, self)
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_attribute(&mut self, mut at: Attribute) -> Option<Attribute> {
|
||||
at.node.id.0 = 0;
|
||||
fold::noop_fold_attribute(at, self)
|
||||
}
|
||||
|
||||
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
||||
fold::noop_fold_mac(mac, self)
|
||||
}
|
||||
}
|
||||
|
||||
Respanner.fold_crate(krate)
|
||||
}
|
@ -1,606 +0,0 @@
|
||||
extern crate syn;
|
||||
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
|
||||
/// These are all of the items from serde_codegen's test suite.
|
||||
/// Obnoxious whitespace has been added in an attempt to fool the parser.
|
||||
#[test]
|
||||
fn test_all() {
|
||||
for s in ITEMS {
|
||||
let ast = syn::parse_macro_input(s).unwrap();
|
||||
let tokens = quote!(#ast).to_string();
|
||||
assert_eq!(ast, syn::parse_macro_input(&tokens).unwrap());
|
||||
}
|
||||
|
||||
static ITEMS: &'static [&'static str] = &[
|
||||
r#"
|
||||
# [ derive ( Serialize ) ]
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultStruct <A , B, C, D, E> where C : MyDefault , E: MyDefault {
|
||||
a1 : A,
|
||||
#[serde(default)]
|
||||
a2: B,
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a3: C,
|
||||
#[serde(skip_deserializing)]
|
||||
a4: D,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
a5: E,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum DefaultEnum<A, B, C, D, E> where C: MyDefault, E: MyDefault {
|
||||
Struct {
|
||||
a1: A,
|
||||
#[serde(default)]
|
||||
a2: B,
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a3: C,
|
||||
#[serde(skip_deserializing)]
|
||||
a4: D,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
a5: E,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct NoStdDefault(i8);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct ContainsNoStdDefault <A : MyDefault> {
|
||||
#[serde(default = "MyDefault::my_default")]
|
||||
a: A,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct ContainsNotDeserialize<A, B, C: DeserializeWith, E: MyDefault> {
|
||||
#[serde(skip_deserializing)]
|
||||
a: A,
|
||||
#[serde(skip_deserializing, default)]
|
||||
b: B,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with", default)]
|
||||
c: C,
|
||||
#[serde(skip_deserializing, default = "MyDefault::my_default")]
|
||||
e: E,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
#[derive(Deserialize)]
|
||||
struct DenyUnknown {
|
||||
a1: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename = "Superhero")]
|
||||
#[derive(Deserialize)]
|
||||
struct RenameStruct {
|
||||
a1: i32,
|
||||
#[serde(rename = "a3")]
|
||||
a2: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename(serialize = "SuperheroSer", deserialize = "SuperheroDe"))]
|
||||
#[derive(Deserialize)]
|
||||
struct RenameStructSerializeDeserialize {
|
||||
a1: i32,
|
||||
#[serde(rename(serialize = "a4", deserialize = "a5"))]
|
||||
a2: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename = "Superhero")]
|
||||
#[derive(Deserialize)]
|
||||
enum RenameEnum {
|
||||
|
||||
#[serde(rename = "bruce_wayne")]
|
||||
Batman ,
|
||||
|
||||
#[serde(rename = "clark_kent")]
|
||||
Superman ( i8 ) ,
|
||||
|
||||
#[serde(rename = "diana_prince")]
|
||||
WonderWoman ( i8 , i8 ) ,
|
||||
|
||||
#[serde(rename = "barry_allan")]
|
||||
Flash {
|
||||
#[serde(rename = "b")]
|
||||
a : i32,
|
||||
} ,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
#[serde ( rename ( serialize = "SuperheroSer" , deserialize = "SuperheroDe" ) ) ]
|
||||
#[derive(Serialize)]
|
||||
enum RenameEnumSerializeDeserialize<A> {
|
||||
|
||||
#[serde(rename(serialize = "dick_grayson", deserialize = "jason_todd"))]
|
||||
Robin {
|
||||
a: i8,
|
||||
#[serde(rename(serialize = "c"))]
|
||||
#[serde(rename(deserialize = "d"))]
|
||||
b: A,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct SkipSerializingStruct< 'a , B, C> where C : ShouldSkip {
|
||||
a: & 'a i8,
|
||||
#[serde(skip_serializing)]
|
||||
b: B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
|
||||
c: C,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
enum SkipSerializingEnum<'a, B, C> where C: ShouldSkip {
|
||||
Struct {
|
||||
a: &'a i8,
|
||||
#[serde(skip_serializing)]
|
||||
_b: B,
|
||||
#[serde(skip_serializing_if = "ShouldSkip::should_skip")]
|
||||
c: C,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct ContainsNotSerialize<'a, B, C, D> where B: 'a , D: SerializeWith {
|
||||
a: &'a Option<i8>,
|
||||
#[serde(skip_serializing)]
|
||||
b: &'a B,
|
||||
#[serde(skip_serializing)]
|
||||
c: Option<C>,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
d: D,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct SerializeWithStruct<'a, B> where B: SerializeWith {
|
||||
a: &'a i8,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
b: B,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
enum SerializeWithEnum<'a, B> where B: SerializeWith {
|
||||
Struct {
|
||||
a: &'a i8,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with")]
|
||||
b: B,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct DeserializeWithStruct<B> where B: DeserializeWith {
|
||||
a: i8,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
b: B,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
enum DeserializeWithEnum<B> where B: DeserializeWith {
|
||||
Struct {
|
||||
a: i8,
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
b: B,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
enum InvalidLengthEnum {
|
||||
A(i32, i32, i32),
|
||||
B(
|
||||
#[serde(skip_deserializing)]
|
||||
i32, i32, i32),
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct TupleStruct(i32, i32, i32);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
#[serde(skip_deserializing)]
|
||||
c: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
enum Enum {
|
||||
Unit,
|
||||
Simple(i32),
|
||||
Seq(i32, i32, i32),
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct IgnoreBase {
|
||||
a: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct With<T> {
|
||||
t: T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct WithRef<'a, T: 'a> {
|
||||
#[serde(skip_deserializing)]
|
||||
t: Option<&'a T>,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct PhantomX {
|
||||
x: PhantomData<X>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct PhantomT<T> {
|
||||
t: PhantomData<T>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct NoBounds<T> {
|
||||
t: T,
|
||||
option: Option<T>,
|
||||
boxed: Box<T>,
|
||||
option_boxed: Option<Box<T>>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum EnumWith<T> {
|
||||
Unit,
|
||||
Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X),
|
||||
Tuple(T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X),
|
||||
Struct {
|
||||
t: T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
x: X,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct MultipleRef<'a, 'b, 'c, T> where T: 'c, 'c: 'b, 'b: 'a {
|
||||
t: T,
|
||||
rrrt: &'a &'b &'c T,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Newtype(
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Tuple<T>(T,
|
||||
#[serde(serialize_with = "ser_x", deserialize_with = "de_x")]
|
||||
X);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum TreeNode<D> {
|
||||
Split {
|
||||
left: Box<TreeNode<D>>,
|
||||
right: Box<TreeNode<D>>,
|
||||
},
|
||||
Leaf {
|
||||
data: D,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct ListNode<D> {
|
||||
data: D,
|
||||
next: Box<ListNode<D>>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct RecursiveA {
|
||||
b: Box<RecursiveB>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum RecursiveB { A(RecursiveA), }
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct RecursiveGenericA<T> {
|
||||
t: T,
|
||||
b: Box<RecursiveGenericB<T>>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum RecursiveGenericB<T> { T(T), A(RecursiveGenericA<T>), }
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct OptionStatic<'a> {
|
||||
a: Option<&'a str>,
|
||||
b: Option<&'static str>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound = "D: SerializeWith + DeserializeWith")]
|
||||
#[derive(Deserialize)]
|
||||
struct WithTraits1<D, E> {
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound = "E: SerializeWith + DeserializeWith")]
|
||||
e: E,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound(serialize = "D: SerializeWith",
|
||||
deserialize = "D: DeserializeWith"))]
|
||||
#[derive(Deserialize)]
|
||||
struct WithTraits2<D, E> {
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
deserialize_with = "DeserializeWith::deserialize_with")]
|
||||
d: D,
|
||||
#[serde(serialize_with = "SerializeWith::serialize_with",
|
||||
bound(serialize = "E: SerializeWith"))]
|
||||
#[serde(deserialize_with = "DeserializeWith::deserialize_with",
|
||||
bound(deserialize = "E: DeserializeWith"))]
|
||||
e: E,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct CowStr<'a>(Cow<'a, str>);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[serde(bound(deserialize = "T::Owned: Deserialize"))]
|
||||
#[derive(Deserialize)]
|
||||
struct CowT < 'a , T : ? Sized + 'a + ToOwned > ( Cow < 'a , T > ) ;
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct SerNamedTuple<'a, 'b, A: 'a, B: 'b, C>(&'a A, &'b mut B, C);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct DeNamedTuple<A, B, C>(A, B, C);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct SerNamedMap<'a, 'b, A: 'a, B: 'b, C> {
|
||||
a: &'a A,
|
||||
b: &'b mut B,
|
||||
c: C,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
struct DeNamedMap<A, B, C> {
|
||||
a: A,
|
||||
b: < Vec < T > as a :: b :: Trait > :: AssociatedItem,
|
||||
c: < Vec < T > > :: AssociatedItem,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
enum SerEnum<'a, B: 'a, C: 'a, D> where for < 'a > D: 'a {
|
||||
Unit,
|
||||
Seq(i8, B, &'a C, &'a mut D),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: &'a C,
|
||||
d: &'a mut D,
|
||||
},
|
||||
_Unit2,
|
||||
_Seq2(i8, B, &'a C, &'a mut D),
|
||||
_Map2 {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: &'a C,
|
||||
d: &'a mut D,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
enum DeEnum<B, C, D> {
|
||||
Unit,
|
||||
Seq(i8, B, C, D),
|
||||
Map {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
},
|
||||
_Unit2,
|
||||
_Seq2(i8, B, C, D),
|
||||
_Map2 {
|
||||
a: i8,
|
||||
b: B,
|
||||
c: C,
|
||||
d: D,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
enum Lifetimes<'a> {
|
||||
LifetimeSeq(&'a i32),
|
||||
NoLifetimeSeq(i32),
|
||||
LifetimeMap {
|
||||
a: &'a i32,
|
||||
},
|
||||
NoLifetimeMap {
|
||||
a: i32,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericStruct<T> {
|
||||
x: T,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericNewTypeStruct<T>(T);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub struct GenericTupleStruct<T, U>(T, U);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
pub enum GenericEnum<T, U: for < 'a > F<'a>> {
|
||||
Unit,
|
||||
NewType(T),
|
||||
Seq(T, U),
|
||||
Map {
|
||||
x: T,
|
||||
y: U,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct DefaultTyParam<T: AssociatedType<X = i32> = i32> {
|
||||
phantom: std :: marker :: PhantomData<T>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct UnitStruct;
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct TupleStruct(i32, i32, i32);
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
struct Struct {
|
||||
a: i32,
|
||||
b: i32,
|
||||
c: i32,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
enum Enum {
|
||||
Unit,
|
||||
One(i32),
|
||||
Seq(i32, i32),
|
||||
Map {
|
||||
a: i32,
|
||||
b: i32,
|
||||
},
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct Bounds<T: Serialize + Deserialize> {
|
||||
t: T,
|
||||
option: Option<T>,
|
||||
boxed: Box<T>,
|
||||
option_boxed: Option<Box<T>>,
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
#[rustc_copy_clone_marker]
|
||||
struct UnitStruct;
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[allow(dead_code)]
|
||||
#[deny(unused_variables)]
|
||||
enum Void { }
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Serialize)]
|
||||
#[derive(Deserialize)]
|
||||
struct NamedUnit;
|
||||
"#,
|
||||
r#"
|
||||
#[derive(Deserialize)]
|
||||
#[doc = r" A custom basic event not covered by the Matrix specification."]
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CustomEvent {
|
||||
/// The event's content.
|
||||
content: String,
|
||||
}
|
||||
"#,
|
||||
];
|
||||
}
|
Loading…
Reference in New Issue
Block a user