abstract-bits-derive 0.2.0

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

use crate::codegen::{is_primitive, list_len_ident};

pub fn read(controlled: &Ident, bits: usize, struct_name: &Literal) -> TokenStream {
    let list_name = Literal::string(&controlled.to_string());
    let len_ident = list_len_ident(controlled);
    if let Some(ty) = is_primitive(bits) {
        quote_spanned! {controlled.span()=>
            let #len_ident = #ty::read_abstract_bits(reader)
                .map_err(|cause| cause.read_list_length(#struct_name, #list_name))?;
        }
    } else {
        let utype: syn::Type =
            syn::parse_str(&format!("::abstract_bits::u{bits}")).expect("valid type path");
        quote_spanned! {controlled.span()=>
            let #len_ident = #utype::read_abstract_bits(reader)
                .map_err(|cause| cause.read_list_length(#struct_name, #list_name))?;
            let #len_ident = #len_ident.value();
        }
    }
}

pub fn write(controlled: &Ident, bits: usize) -> TokenStream {
    let len_ident = list_len_ident(controlled);
    if let Some(ty) = is_primitive(bits) {
        quote_spanned! {controlled.span()=>
            let #len_ident: #ty = self.#controlled.len().try_into()
                .map_err(|_| ::abstract_bits::ToBytesError::ListTooLong {
                    max: #ty::MAX as usize,
                    got: self.#controlled.len(),
            })?;
            ::abstract_bits::AbstractBits::write_abstract_bits(&#len_ident, writer)?;
        }
    } else {
        let utype: syn::Type =
            syn::parse_str(&format!("::abstract_bits::u{bits}")).expect("valid type path");
        quote_spanned! {controlled.span()=>
            let #len_ident = self.#controlled.len().try_into()
                .map_err(|_| ::abstract_bits::ToBytesError::ListTooLong {
                    max: 2usize.pow(#utype::BITS as u32) - 1,
                    got: self.#controlled.len(),
                })?;
            let #len_ident = #utype::try_new(#len_ident)
                .map_err(|_| ::abstract_bits::ToBytesError::ListTooLong {
                    max: 2usize.pow(#utype::BITS as u32) - 1,
                    got: self.#controlled.len(),
                })?;
            ::abstract_bits::AbstractBits::write_abstract_bits(&#len_ident, writer)?;
        }
    }
}

pub(crate) fn min_bits(n_bits: usize) -> TokenStream {
    let n_bits = proc_macro2::Literal::usize_unsuffixed(n_bits);
    quote! {
        #n_bits
    }
}

pub(crate) fn max_bits(n_bits: usize) -> TokenStream {
    let n_bits = proc_macro2::Literal::usize_unsuffixed(n_bits);
    quote! {
        #n_bits
    }
}