fn field_serializer()

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)
}