delta-pack-derive 0.3.0

Proc-macro derive for delta-pack
Documentation
use proc_macro2::TokenStream;

#[derive(Clone)]
pub enum Type {
    String,
    Int(IntInfo),
    Float { precision: Option<f32> },
    Boolean,
    Array(Box<Type>),
    Optional(Box<Type>),
    Record { key: Box<Type>, value: Box<Type> },
    Reference(syn::Path),
    SelfReference,
}

#[derive(Clone, Debug)]
pub struct IntInfo {
    pub min: Option<i64>,
    pub max: Option<i64>,
    pub num_bits: Option<u8>,
    pub storage: IntStorage,
}

#[derive(Clone, Debug)]
pub enum IntStorage {
    I8,
    I16,
    I32,
    I64,
    U8,
    U16,
    U32,
    U64,
}

impl IntStorage {
    pub fn is_signed(&self) -> bool {
        matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64)
    }

    pub fn as_ty(&self) -> TokenStream {
        match self {
            Self::I8 => quote::quote! { i8 },
            Self::I16 => quote::quote! { i16 },
            Self::I32 => quote::quote! { i32 },
            Self::I64 => quote::quote! { i64 },
            Self::U8 => quote::quote! { u8 },
            Self::U16 => quote::quote! { u16 },
            Self::U32 => quote::quote! { u32 },
            Self::U64 => quote::quote! { u64 },
        }
    }
}

pub fn compute_num_bits(min: i64, max: i64) -> Option<u8> {
    if max < min {
        return None;
    }
    let range = (max as i128) - (min as i128) + 1;
    let bits = if range <= 1 {
        1
    } else {
        (range as f64).log2().ceil() as u32
    };
    if bits <= 8 {
        Some(bits as u8)
    } else {
        None
    }
}

pub enum IntStrategy {
    Packed { offset: i64, max: i64, num_bits: u8 },
    Unsigned { min: i64 },
    Signed,
}

pub fn int_strategy(info: &IntInfo) -> IntStrategy {
    if let (Some(min), Some(max), Some(num_bits)) = (info.min, info.max, info.num_bits) {
        return IntStrategy::Packed {
            offset: min,
            max,
            num_bits,
        };
    }
    if let Some(min) = info.min {
        if min >= 0 {
            return IntStrategy::Unsigned { min };
        }
    }
    IntStrategy::Signed
}

pub enum FloatStrategy {
    Quantized { precision: f32 },
    Full,
}

pub fn float_strategy(precision: Option<f32>) -> FloatStrategy {
    match precision {
        Some(p) if p != 0.0 => FloatStrategy::Quantized { precision: p },
        _ => FloatStrategy::Full,
    }
}