in lain_derive/src/serialize.rs [213:289]
fn field_serializer(
field: &Field,
name_prefix: &'static str,
is_destructured: bool,
) -> (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 endian = if field.attrs.big_endian() {
quote! {_lain::byteorder::BigEndian}
} else if field.attrs.little_endian() {
quote! {_lain::byteorder::LittleEndian}
} else {
// inherit
quote! {E}
};
let serialize_stmts = if let Some(bits) = field.attrs.bits() {
let bit_mask = 2_u64.pow(bits as u32) - 1;
let bit_shift = field.attrs.bit_shift().unwrap();
let is_last_field = field.attrs.is_last_field();
let bitfield_type = field.attrs.bitfield_type().unwrap_or(&field.ty);
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 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.ty.span() => #value_ident.to_primitive()}
} else {
quote_spanned! {field.original.span() => #value_ident}
};
let mut bitfield_setter = quote_spanned! { field.ty.span() =>
bitfield |= ((#bitfield_value as #bitfield_type & #bit_mask as #bitfield_type) << #bit_shift) as u64;
};
if bits + bit_shift == type_total_bits || is_last_field {
bitfield_setter.extend(quote_spanned!{field.ty.span() => bytes_written += <#bitfield_type>::binary_serialize::<_, #endian>(&(bitfield as #bitfield_type), buffer);});
}
bitfield_setter
} else {
if let syn::Type::Array(ref _a) = ty {
// TODO: Change this once const generics are stabilized
quote_spanned! { field.original.span() =>
bytes_written += #value_ident.binary_serialize::<_, #endian>(buffer);
}
} else {
quote_spanned! { field.original.span() =>
bytes_written += <#ty>::binary_serialize::<_, #endian>(#borrow#value_ident, buffer);
}
}
};
(value_ident, field_ident_string, serialize_stmts)
}