abstract-bits-derive 0.2.0

Turn bit & byte sequences into normal structs
Documentation
use proc_macro2::Literal;
use proc_macro2::TokenStream;
use quote::{ToTokens, quote_spanned};
use syn::spanned::Spanned;

use crate::codegen::generics_to_fully_qualified;
use crate::model::NormalField;

pub fn read(
    NormalField {
        ident,
        out_ty,
        bits,
        ..
    }: &NormalField,
    struct_name: &Literal,
) -> TokenStream {
    let field_name = proc_macro2::Literal::string(&ident.to_string());
    if let Some(bits) = bits {
        let utype: syn::Type = syn::parse_str(&format!("::abstract_bits::u{bits}"))
            .expect("should be valid type path");
        quote_spanned! {out_ty.span()=>
            let #ident = #utype::read_abstract_bits(reader)
                .map_err(|cause| cause.read_field(#struct_name, #field_name))?;
            let #ident = #ident.value();
        }
    } else {
        let out_ty = generics_to_fully_qualified(out_ty.clone());
        quote_spanned! {out_ty.span()=>
            let #ident = #out_ty::read_abstract_bits(reader)
                .map_err(|cause| cause.read_field(#struct_name, #field_name))?;
        }
    }
}

pub fn write(
    NormalField {
        ident,
        out_ty,
        bits,
        ..
    }: &NormalField,
) -> TokenStream {
    if let Some(bits) = *bits {
        let utype: syn::Type = syn::parse_str(&format!("::abstract_bits::u{bits}"))
            .expect("should be valid type path");
        quote_spanned! {out_ty.span()=>
            let #ident = #utype::new(self.#ident);
            #ident.write_abstract_bits(writer)?;
        }
    } else {
        quote_spanned! {out_ty.span()=>
            self.#ident.write_abstract_bits(writer)?;
        }
    }
}

pub(crate) fn min_bits(normal_field: &crate::model::NormalField) -> TokenStream {
    let ty = &normal_field.out_ty;
    if let Some(n) = normal_field.bits {
        proc_macro2::Literal::usize_unsuffixed(n as usize).to_token_stream()
    } else {
        quote_spanned! {normal_field.ident.span()=>
            #ty::MIN_BITS
        }
    }
}

pub(crate) fn max_bits(normal_field: &crate::model::NormalField) -> TokenStream {
    let ty = &normal_field.out_ty;
    if let Some(n) = normal_field.bits {
        proc_macro2::Literal::usize_unsuffixed(n as usize).to_token_stream()
    } else {
        quote_spanned! {normal_field.ident.span()=>
                #ty::MAX_BITS
        }
    }
}