dbstruct-derive 0.1.0-alpha

Build a typed database by defining a struct
Documentation
use std::collections::HashMap;
use syn::Ident;

use crate::errors::GetSpan;

#[derive(thiserror::Error, Debug)]
#[error("A dbstruct can only have 254 fields")]
pub struct Error {
    span: proc_macro2::Span,
}

impl GetSpan for Error {
    fn span(&self) -> proc_macro2::Span {
        self.span
    }
}

type Prefix = u8;
#[derive(Debug)]
pub struct DbKey(HashMap<Ident, Prefix>);

impl DbKey {
    #[cfg(test)]
    /// inserts ident test_a till test_d with keys 0..
    pub(crate) fn mock() -> Self {
        Self(
            ["test_a", "test_b", "test_c", "test_d"]
                .into_iter()
                .map(|id| Ident::new(id, proc_macro2::Span::call_site()))
                .enumerate()
                .map(|(a, b)| (b, a as u8))
                .collect(),
        )
    }

    pub(crate) fn new(fields: &syn::Fields) -> Result<Self, Error> {
        let mut idents: Vec<_> = fields
            .iter()
            .map(|f| f.ident.clone())
            .map(|i| i.expect("should already be verified this is a named struct"))
            .collect();
        idents.sort();

        if let Some(ident) = idents.get(u8::MAX as usize) {
            return Err(Error { span: ident.span() });
        };

        let map = idents
            .into_iter()
            .enumerate()
            .map(|(id, ident)| (ident, id as Prefix))
            .collect();
        Ok(Self(map))
    }

    pub fn prefix(&self, ident: &Ident) -> Prefix {
        *self
            .0
            .get(ident)
            .expect("every field's ident should be in the DbKey map")
    }
}