mirror of
https://github.com/serde-rs/serde.git
synced 2025-10-01 15:01:49 +00:00
Add support for packed structs.
This commit is contained in:
parent
d6b39fd2c1
commit
9f47c47cad
@ -222,6 +222,7 @@ pub struct Container {
|
|||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
has_flatten: bool,
|
has_flatten: bool,
|
||||||
serde_path: Option<syn::Path>,
|
serde_path: Option<syn::Path>,
|
||||||
|
is_packed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Styles of representing an enum.
|
/// Styles of representing an enum.
|
||||||
@ -592,6 +593,27 @@ impl Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use proc_macro2::Delimiter;
|
||||||
|
let is_packed = item.attrs.iter().any(|attr| {
|
||||||
|
match attr.style {
|
||||||
|
syn::AttrStyle::Outer => attr
|
||||||
|
.path
|
||||||
|
.get_ident()
|
||||||
|
.map_or(false, |ident| *ident == "repr")
|
||||||
|
&& syn::parse2::<Group>(attr.tokens.clone())
|
||||||
|
.ok()
|
||||||
|
.filter(|g| g.delimiter() == Delimiter::Parenthesis)
|
||||||
|
.map(|g| g.stream().to_string())
|
||||||
|
.map_or(false, |repr| {
|
||||||
|
let repr = repr.trim();
|
||||||
|
repr == "packed"
|
||||||
|
|| repr.starts_with("packed(")
|
||||||
|
|| repr.starts_with("packed ")
|
||||||
|
}),
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Container {
|
Container {
|
||||||
name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
|
name: Name::from_attrs(unraw(&item.ident), ser_name, de_name, None),
|
||||||
transparent: transparent.get(),
|
transparent: transparent.get(),
|
||||||
@ -611,6 +633,7 @@ impl Container {
|
|||||||
identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
|
identifier: decide_identifier(cx, item, field_identifier, variant_identifier),
|
||||||
has_flatten: false,
|
has_flatten: false,
|
||||||
serde_path: serde_path.get(),
|
serde_path: serde_path.get(),
|
||||||
|
is_packed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -662,6 +685,10 @@ impl Container {
|
|||||||
self.remote.as_ref()
|
self.remote.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_packed(&self) -> bool {
|
||||||
|
self.is_packed
|
||||||
|
}
|
||||||
|
|
||||||
pub fn identifier(&self) -> Identifier {
|
pub fn identifier(&self) -> Identifier {
|
||||||
self.identifier
|
self.identifier
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,9 @@ struct Parameters {
|
|||||||
|
|
||||||
/// Type has a `serde(remote = "...")` attribute.
|
/// Type has a `serde(remote = "...")` attribute.
|
||||||
is_remote: bool,
|
is_remote: bool,
|
||||||
|
|
||||||
|
/// Type has a repr(packed) attribute.
|
||||||
|
is_packed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parameters {
|
impl Parameters {
|
||||||
@ -103,6 +106,8 @@ impl Parameters {
|
|||||||
None => cont.ident.clone().into(),
|
None => cont.ident.clone().into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let is_packed = cont.attrs.is_packed();
|
||||||
|
|
||||||
let generics = build_generics(cont);
|
let generics = build_generics(cont);
|
||||||
|
|
||||||
Parameters {
|
Parameters {
|
||||||
@ -110,6 +115,7 @@ impl Parameters {
|
|||||||
this,
|
this,
|
||||||
generics,
|
generics,
|
||||||
is_remote,
|
is_remote,
|
||||||
|
is_packed,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,9 +1244,19 @@ fn mut_if(is_mut: bool) -> Option<TokenStream> {
|
|||||||
fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
|
fn get_member(params: &Parameters, field: &Field, member: &Member) -> TokenStream {
|
||||||
let self_var = ¶ms.self_var;
|
let self_var = ¶ms.self_var;
|
||||||
match (params.is_remote, field.attrs.getter()) {
|
match (params.is_remote, field.attrs.getter()) {
|
||||||
(false, None) => quote!(&#self_var.#member),
|
(false, None) => {
|
||||||
|
if params.is_packed {
|
||||||
|
quote!(&{let copy = #self_var.#member; copy })
|
||||||
|
} else {
|
||||||
|
quote!(&#self_var.#member)
|
||||||
|
}
|
||||||
|
}
|
||||||
(true, None) => {
|
(true, None) => {
|
||||||
let inner = quote!(&#self_var.#member);
|
let inner = if params.is_packed {
|
||||||
|
quote!(&{let copy = #self_var.#member; copy })
|
||||||
|
} else {
|
||||||
|
quote!(&#self_var.#member)
|
||||||
|
};
|
||||||
let ty = field.ty;
|
let ty = field.ty;
|
||||||
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
quote!(_serde::private::ser::constrain::<#ty>(#inner))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user