kosame_macro 0.0.3

Macro-based Rust ORM focused on developer ergonomics
Documentation
use std::{fmt::Display, ops::Deref};

use syn::{
    Token,
    parse::{Parse, ParseStream},
};

use crate::expr::Expr;

pub struct ColumnConstraints(Vec<ColumnConstraint>);

impl ColumnConstraints {
    pub fn not_null(&self) -> Option<&NotNull> {
        self.0.iter().find_map(|c| match c {
            ColumnConstraint::NotNull(inner) => Some(inner),
            _ => None,
        })
    }

    pub fn primary_key(&self) -> Option<&PrimaryKey> {
        self.0.iter().find_map(|c| match c {
            ColumnConstraint::PrimaryKey(inner) => Some(inner),
            _ => None,
        })
    }

    pub fn default(&self) -> Option<&Default> {
        self.0.iter().find_map(|c| match c {
            ColumnConstraint::Default(inner) => Some(inner),
            _ => None,
        })
    }
}

impl Parse for ColumnConstraints {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let mut constraints = vec![];
        while !input.is_empty() && !input.peek(Token![,]) {
            constraints.push(input.parse()?);
        }
        Ok(Self(constraints))
    }
}

impl Deref for ColumnConstraints {
    type Target = Vec<ColumnConstraint>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

#[allow(unused)]
pub enum ColumnConstraint {
    NotNull(NotNull),
    PrimaryKey(PrimaryKey),
    Default(Default),
}

impl Parse for ColumnConstraint {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let lookahead = input.lookahead1();
        if lookahead.peek(kw::not) {
            Ok(Self::NotNull(input.parse()?))
        } else if lookahead.peek(kw::primary) {
            Ok(Self::PrimaryKey(input.parse()?))
        } else if lookahead.peek(kw::default) {
            Ok(Self::Default(input.parse()?))
        } else {
            Err(lookahead.error())
        }
    }
}

impl Display for ColumnConstraint {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::NotNull(_) => f.write_str("not null")?,
            Self::PrimaryKey(_) => f.write_str("primary key")?,
            Self::Default(_) => f.write_str("default ...")?,
        };
        Ok(())
    }
}

mod kw {
    syn::custom_keyword!(not);
    syn::custom_keyword!(null);

    syn::custom_keyword!(default);

    syn::custom_keyword!(primary);
    syn::custom_keyword!(key);

    syn::custom_keyword!(references);
}

pub struct NotNull {
    _not: kw::not,
    _null: kw::null,
}

impl Parse for NotNull {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            _not: input.parse()?,
            _null: input.parse()?,
        })
    }
}

pub struct PrimaryKey {
    _primary: kw::primary,
    _key: kw::key,
}

impl Parse for PrimaryKey {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            _primary: input.parse()?,
            _key: input.parse()?,
        })
    }
}

pub struct Default {
    _default: kw::default,
    expr: Expr,
}

impl Parse for Default {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            _default: input.parse()?,
            expr: input.parse()?,
        })
    }
}