in lain_derive/src/serialize.rs [441:543]
fn field_serialized_size(
field: &Field,
name_prefix: &'static str,
is_destructured: bool,
visitor_type: SerializedSizeVisitorType,
) -> (TokenStream, String, TokenStream) {
let ty = &field.ty;
let field_ident_string = match field.member {
syn::Member::Named(ref ident) => ident.to_string(),
syn::Member::Unnamed(ref idx) => idx.index.to_string(),
};
let value_ident =
TokenStream::from_str(&format!("{}{}", name_prefix, field_ident_string)).unwrap();
let borrow = if is_destructured {
TokenStream::new()
} else {
quote! {&}
};
let serialized_size_stmts = if let Some(bits) = field.attrs.bits() {
let bit_shift = field.attrs.bit_shift().unwrap();
let bitfield_type = field.attrs.bitfield_type().unwrap_or(&field.ty);
let is_last_field = field.attrs.is_last_field();
let type_total_bits = if is_primitive_type(bitfield_type, "u8") {
8
} else if is_primitive_type(&bitfield_type, "u16") {
16
} else if is_primitive_type(&bitfield_type, "u32") {
32
} else if is_primitive_type(&bitfield_type, "u64") {
64
} else {
panic!("got to field_serialize_size with an unsupported bitfield type `{}`. ensure that checks in ast code are correct", bitfield_type.into_token_stream());
};
let bitfield_value = if field.attrs.bitfield_type().is_some() {
quote_spanned! {field.original.span() => #borrow#value_ident.to_primitive()}
} else {
quote_spanned! { field.original.span() => #borrow#value_ident}
};
// kind of a hack but only emit the size of the bitfield for the first element
if bits + bit_shift == type_total_bits || is_last_field {
match visitor_type {
SerializedSizeVisitorType::SerializedSize => {
quote_spanned! {field.original.span() => _lain::traits::SerializedSize::serialized_size(#bitfield_value)}
}
SerializedSizeVisitorType::MinNonzeroElements
| SerializedSizeVisitorType::MinEnumVariantSize => {
quote_spanned! {field.original.span() => <#bitfield_type>::min_nonzero_elements_size()}
}
SerializedSizeVisitorType::MaxDefaultObjectSize => {
quote_spanned! {field.original.span() => <#bitfield_type>::max_default_object_size()}
}
}
} else {
quote! {0 /* bitfield */}
}
} else {
match visitor_type {
SerializedSizeVisitorType::SerializedSize => {
quote_spanned! { field.original.span() => _lain::traits::SerializedSize::serialized_size(#borrow#value_ident)}
}
SerializedSizeVisitorType::MinNonzeroElements
| SerializedSizeVisitorType::MinEnumVariantSize => match ty {
syn::Type::Path(ref p)
if p.path.segments[0].ident == "Vec" && field.attrs.min().is_some() =>
{
let min = field.attrs.min().unwrap();
quote_spanned! { field.original.span() => <#ty>::min_nonzero_elements_size() * #min }
}
_ => {
quote_spanned! { field.original.span() => (<#ty>::min_nonzero_elements_size() ) }
}
},
SerializedSizeVisitorType::MaxDefaultObjectSize => match ty {
syn::Type::Path(ref p)
if p.path.segments[0].ident == "Vec" && field.attrs.min().is_some() =>
{
let min = field
.attrs
.min()
.map(|min| {
if min.to_string() == "0" {
quote! {1}
} else {
min.clone()
}
})
.unwrap_or(quote! {1});
quote_spanned! { field.original.span() => <#ty>::max_default_object_size() * #min }
}
_ => {
quote_spanned! { field.original.span() => (<#ty>::max_default_object_size() ) }
}
},
}
};
(value_ident, field_ident_string, serialized_size_stmts)
}