Skip to content

Commit 6f37f9b

Browse files
committed
rust: serde_derive: import crate
This is a subset of the Rust `serde_derive` crate, version v1.0.156, licensed under "Apache-2.0 OR MIT", from: https://github.com/serde-rs/serde/tree/v1.0.156/serde_derive/src The files are copied as-is, with no modifications whatsoever (not even adding the SPDX identifiers). For copyright details, please see: https://github.com/serde-rs/serde/blob/v1.0.156/README.md#license https://github.com/serde-rs/serde/blob/v1.0.156/LICENSE-APACHE https://github.com/serde-rs/serde/blob/v1.0.156/LICENSE-MIT The next patch modifies these files as needed for use within the kernel. This patch split allows reviewers to double-check the import and to clearly see the differences introduced. The following script may be used to verify the contents: for path in $(cd rust/serde_derive/ && find . -type f -name '*.rs'); do curl --silent --show-error --location \ https://github.com/serde-rs/serde/raw/v1.0.156/serde_derive/src/$path \ | diff --unified rust/serde_derive/$path - && echo $path: OK done Signed-off-by: Miguel Ojeda <[email protected]>
1 parent b56a317 commit 6f37f9b

File tree

18 files changed

+8585
-0
lines changed

18 files changed

+8585
-0
lines changed

rust/serde_derive/bound.rs

Lines changed: 406 additions & 0 deletions
Large diffs are not rendered by default.

rust/serde_derive/de.rs

Lines changed: 3146 additions & 0 deletions
Large diffs are not rendered by default.

rust/serde_derive/dummy.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use proc_macro2::{Ident, TokenStream};
2+
use quote::format_ident;
3+
4+
use syn;
5+
use try;
6+
7+
pub fn wrap_in_const(
8+
serde_path: Option<&syn::Path>,
9+
trait_: &str,
10+
ty: &Ident,
11+
code: TokenStream,
12+
) -> TokenStream {
13+
let try_replacement = try::replacement();
14+
15+
let dummy_const = if cfg!(no_underscore_consts) {
16+
format_ident!("_IMPL_{}_FOR_{}", trait_, unraw(ty))
17+
} else {
18+
format_ident!("_")
19+
};
20+
21+
let use_serde = match serde_path {
22+
Some(path) => quote! {
23+
use #path as _serde;
24+
},
25+
None => quote! {
26+
#[allow(unused_extern_crates, clippy::useless_attribute)]
27+
extern crate serde as _serde;
28+
},
29+
};
30+
31+
quote! {
32+
#[doc(hidden)]
33+
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
34+
const #dummy_const: () = {
35+
#use_serde
36+
#try_replacement
37+
#code
38+
};
39+
}
40+
}
41+
42+
fn unraw(ident: &Ident) -> String {
43+
ident.to_string().trim_start_matches("r#").to_owned()
44+
}

rust/serde_derive/fragment.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use proc_macro2::TokenStream;
2+
use quote::ToTokens;
3+
use syn::token;
4+
5+
pub enum Fragment {
6+
/// Tokens that can be used as an expression.
7+
Expr(TokenStream),
8+
/// Tokens that can be used inside a block. The surrounding curly braces are
9+
/// not part of these tokens.
10+
Block(TokenStream),
11+
}
12+
13+
macro_rules! quote_expr {
14+
($($tt:tt)*) => {
15+
$crate::fragment::Fragment::Expr(quote!($($tt)*))
16+
}
17+
}
18+
19+
macro_rules! quote_block {
20+
($($tt:tt)*) => {
21+
$crate::fragment::Fragment::Block(quote!($($tt)*))
22+
}
23+
}
24+
25+
/// Interpolate a fragment in place of an expression. This involves surrounding
26+
/// Block fragments in curly braces.
27+
pub struct Expr(pub Fragment);
28+
impl ToTokens for Expr {
29+
fn to_tokens(&self, out: &mut TokenStream) {
30+
match &self.0 {
31+
Fragment::Expr(expr) => expr.to_tokens(out),
32+
Fragment::Block(block) => {
33+
token::Brace::default().surround(out, |out| block.to_tokens(out));
34+
}
35+
}
36+
}
37+
}
38+
39+
/// Interpolate a fragment as the statements of a block.
40+
pub struct Stmts(pub Fragment);
41+
impl ToTokens for Stmts {
42+
fn to_tokens(&self, out: &mut TokenStream) {
43+
match &self.0 {
44+
Fragment::Expr(expr) => expr.to_tokens(out),
45+
Fragment::Block(block) => block.to_tokens(out),
46+
}
47+
}
48+
}
49+
50+
/// Interpolate a fragment as the value part of a `match` expression. This
51+
/// involves putting a comma after expressions and curly braces around blocks.
52+
pub struct Match(pub Fragment);
53+
impl ToTokens for Match {
54+
fn to_tokens(&self, out: &mut TokenStream) {
55+
match &self.0 {
56+
Fragment::Expr(expr) => {
57+
expr.to_tokens(out);
58+
<Token![,]>::default().to_tokens(out);
59+
}
60+
Fragment::Block(block) => {
61+
token::Brace::default().surround(out, |out| block.to_tokens(out));
62+
}
63+
}
64+
}
65+
}
66+
67+
impl AsRef<TokenStream> for Fragment {
68+
fn as_ref(&self) -> &TokenStream {
69+
match self {
70+
Fragment::Expr(expr) => expr,
71+
Fragment::Block(block) => block,
72+
}
73+
}
74+
}

rust/serde_derive/internals/ast.rs

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
//! A Serde ast, parsed from the Syn ast and ready to generate Rust code.
2+
3+
use internals::attr;
4+
use internals::check;
5+
use internals::{Ctxt, Derive};
6+
use syn;
7+
use syn::punctuated::Punctuated;
8+
9+
/// A source data structure annotated with `#[derive(Serialize)]` and/or `#[derive(Deserialize)]`,
10+
/// parsed into an internal representation.
11+
pub struct Container<'a> {
12+
/// The struct or enum name (without generics).
13+
pub ident: syn::Ident,
14+
/// Attributes on the structure, parsed for Serde.
15+
pub attrs: attr::Container,
16+
/// The contents of the struct or enum.
17+
pub data: Data<'a>,
18+
/// Any generics on the struct or enum.
19+
pub generics: &'a syn::Generics,
20+
/// Original input.
21+
pub original: &'a syn::DeriveInput,
22+
}
23+
24+
/// The fields of a struct or enum.
25+
///
26+
/// Analogous to `syn::Data`.
27+
pub enum Data<'a> {
28+
Enum(Vec<Variant<'a>>),
29+
Struct(Style, Vec<Field<'a>>),
30+
}
31+
32+
/// A variant of an enum.
33+
pub struct Variant<'a> {
34+
pub ident: syn::Ident,
35+
pub attrs: attr::Variant,
36+
pub style: Style,
37+
pub fields: Vec<Field<'a>>,
38+
pub original: &'a syn::Variant,
39+
}
40+
41+
/// A field of a struct.
42+
pub struct Field<'a> {
43+
pub member: syn::Member,
44+
pub attrs: attr::Field,
45+
pub ty: &'a syn::Type,
46+
pub original: &'a syn::Field,
47+
}
48+
49+
#[derive(Copy, Clone)]
50+
pub enum Style {
51+
/// Named fields.
52+
Struct,
53+
/// Many unnamed fields.
54+
Tuple,
55+
/// One unnamed field.
56+
Newtype,
57+
/// No fields.
58+
Unit,
59+
}
60+
61+
impl<'a> Container<'a> {
62+
/// Convert the raw Syn ast into a parsed container object, collecting errors in `cx`.
63+
pub fn from_ast(
64+
cx: &Ctxt,
65+
item: &'a syn::DeriveInput,
66+
derive: Derive,
67+
) -> Option<Container<'a>> {
68+
let mut attrs = attr::Container::from_ast(cx, item);
69+
70+
let mut data = match &item.data {
71+
syn::Data::Enum(data) => Data::Enum(enum_from_ast(cx, &data.variants, attrs.default())),
72+
syn::Data::Struct(data) => {
73+
let (style, fields) = struct_from_ast(cx, &data.fields, None, attrs.default());
74+
Data::Struct(style, fields)
75+
}
76+
syn::Data::Union(_) => {
77+
cx.error_spanned_by(item, "Serde does not support derive for unions");
78+
return None;
79+
}
80+
};
81+
82+
let mut has_flatten = false;
83+
match &mut data {
84+
Data::Enum(variants) => {
85+
for variant in variants {
86+
variant.attrs.rename_by_rules(attrs.rename_all_rules());
87+
for field in &mut variant.fields {
88+
if field.attrs.flatten() {
89+
has_flatten = true;
90+
}
91+
field
92+
.attrs
93+
.rename_by_rules(variant.attrs.rename_all_rules());
94+
}
95+
}
96+
}
97+
Data::Struct(_, fields) => {
98+
for field in fields {
99+
if field.attrs.flatten() {
100+
has_flatten = true;
101+
}
102+
field.attrs.rename_by_rules(attrs.rename_all_rules());
103+
}
104+
}
105+
}
106+
107+
if has_flatten {
108+
attrs.mark_has_flatten();
109+
}
110+
111+
let mut item = Container {
112+
ident: item.ident.clone(),
113+
attrs,
114+
data,
115+
generics: &item.generics,
116+
original: item,
117+
};
118+
check::check(cx, &mut item, derive);
119+
Some(item)
120+
}
121+
}
122+
123+
impl<'a> Data<'a> {
124+
pub fn all_fields(&'a self) -> Box<Iterator<Item = &'a Field<'a>> + 'a> {
125+
match self {
126+
Data::Enum(variants) => {
127+
Box::new(variants.iter().flat_map(|variant| variant.fields.iter()))
128+
}
129+
Data::Struct(_, fields) => Box::new(fields.iter()),
130+
}
131+
}
132+
133+
pub fn has_getter(&self) -> bool {
134+
self.all_fields().any(|f| f.attrs.getter().is_some())
135+
}
136+
}
137+
138+
fn enum_from_ast<'a>(
139+
cx: &Ctxt,
140+
variants: &'a Punctuated<syn::Variant, Token![,]>,
141+
container_default: &attr::Default,
142+
) -> Vec<Variant<'a>> {
143+
variants
144+
.iter()
145+
.map(|variant| {
146+
let attrs = attr::Variant::from_ast(cx, variant);
147+
let (style, fields) =
148+
struct_from_ast(cx, &variant.fields, Some(&attrs), container_default);
149+
Variant {
150+
ident: variant.ident.clone(),
151+
attrs,
152+
style,
153+
fields,
154+
original: variant,
155+
}
156+
})
157+
.collect()
158+
}
159+
160+
fn struct_from_ast<'a>(
161+
cx: &Ctxt,
162+
fields: &'a syn::Fields,
163+
attrs: Option<&attr::Variant>,
164+
container_default: &attr::Default,
165+
) -> (Style, Vec<Field<'a>>) {
166+
match fields {
167+
syn::Fields::Named(fields) => (
168+
Style::Struct,
169+
fields_from_ast(cx, &fields.named, attrs, container_default),
170+
),
171+
syn::Fields::Unnamed(fields) if fields.unnamed.len() == 1 => (
172+
Style::Newtype,
173+
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
174+
),
175+
syn::Fields::Unnamed(fields) => (
176+
Style::Tuple,
177+
fields_from_ast(cx, &fields.unnamed, attrs, container_default),
178+
),
179+
syn::Fields::Unit => (Style::Unit, Vec::new()),
180+
}
181+
}
182+
183+
fn fields_from_ast<'a>(
184+
cx: &Ctxt,
185+
fields: &'a Punctuated<syn::Field, Token![,]>,
186+
attrs: Option<&attr::Variant>,
187+
container_default: &attr::Default,
188+
) -> Vec<Field<'a>> {
189+
fields
190+
.iter()
191+
.enumerate()
192+
.map(|(i, field)| Field {
193+
member: match &field.ident {
194+
Some(ident) => syn::Member::Named(ident.clone()),
195+
None => syn::Member::Unnamed(i.into()),
196+
},
197+
attrs: attr::Field::from_ast(cx, i, field, attrs, container_default),
198+
ty: &field.ty,
199+
original: field,
200+
})
201+
.collect()
202+
}

0 commit comments

Comments
 (0)