kosame_dsl 0.3.0

Macro-based Rust ORM focused on developer ergonomics
Documentation
use proc_macro2::TokenStream;
use quote::{ToTokens, quote};
use syn::parse::{Parse, ParseStream};

use crate::{
    clause::{FromChain, Returning, Where},
    keyword,
    parse_option::ParseOption,
    part::TargetTable,
    pretty::{PrettyPrint, Printer},
    quote_option::QuoteOption,
    visit::Visit,
};

pub struct Delete {
    pub delete_keyword: keyword::delete,
    pub from_keyword: keyword::from,
    pub target_table: TargetTable,
    pub using: Option<Using>,
    pub r#where: Option<Where>,
    pub returning: Option<Returning>,
}

impl Delete {
    pub fn peek(input: ParseStream) -> bool {
        input.peek(keyword::delete)
    }
}

pub fn visit_delete<'a>(visit: &mut (impl Visit<'a> + ?Sized), delete: &'a Delete) {
    visit.visit_target_table(&delete.target_table);
    if let Some(inner) = &delete.using {
        visit.visit_using(inner);
    }
    if let Some(inner) = &delete.r#where {
        visit.visit_where(inner);
    }
    if let Some(inner) = &delete.returning {
        visit.visit_returning(inner);
    }
}

impl Parse for Delete {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            delete_keyword: input.parse()?,
            from_keyword: input.parse()?,
            target_table: input.parse()?,
            using: input.call(Using::parse_option)?,
            r#where: input.call(Where::parse_option)?,
            returning: input.call(Returning::parse_option)?,
        })
    }
}

impl ToTokens for Delete {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let target_table = &self.target_table;
        let using = QuoteOption::from(&self.using);
        let r#where = QuoteOption::from(&self.r#where);
        let returning = QuoteOption::from(&self.returning);

        quote! {
            ::kosame::repr::command::Delete::new(
                #target_table,
                #using,
                #r#where,
                #returning,
            )
        }
        .to_tokens(tokens);
    }
}

impl PrettyPrint for Delete {
    fn pretty_print(&self, printer: &mut Printer<'_>) {
        self.delete_keyword.pretty_print(printer);
        " ".pretty_print(printer);
        self.from_keyword.pretty_print(printer);
        printer.scan_indent(1);
        printer.scan_break();
        " ".pretty_print(printer);
        self.target_table.pretty_print(printer);
        printer.scan_indent(-1);
        self.using.pretty_print(printer);
        self.r#where.pretty_print(printer);
        self.returning.pretty_print(printer);
    }
}

pub struct Using {
    pub using_keyword: keyword::using,
    pub chain: FromChain,
}

impl ParseOption for Using {
    fn peek(input: ParseStream) -> bool {
        input.peek(keyword::using)
    }
}

pub fn visit_using<'a>(visit: &mut (impl Visit<'a> + ?Sized), using: &'a Using) {
    visit.visit_from_chain(&using.chain);
}

impl Parse for Using {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        Ok(Self {
            using_keyword: input.parse()?,
            chain: input.parse()?,
        })
    }
}

impl ToTokens for Using {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.chain.to_tokens(tokens);
    }
}

impl PrettyPrint for Using {
    fn pretty_print(&self, printer: &mut Printer<'_>) {
        printer.scan_break();
        printer.scan_trivia(true, true);
        " ".pretty_print(printer);
        self.using_keyword.pretty_print(printer);
        printer.scan_indent(1);
        printer.scan_break();
        " ".pretty_print(printer);
        self.chain.pretty_print(printer);
        printer.scan_indent(-1);
    }
}