easy-sql-macros 1.1.2

Easy SQL support library
Documentation
use proc_macro2::TokenStream;
use quote::{ToTokens, quote, quote_spanned};
use syn::spanned::Spanned;

#[derive(Debug, Clone)]
pub enum ProvidedDrivers {
    Single(TokenStream),
    SingleWithChecks {
        driver: TokenStream,
        checks: Vec<TokenStream>,
    },
    MultipleWithConn {
        drivers: Vec<TokenStream>,
        conn: TokenStream,
    },
}

impl ProvidedDrivers {
    pub fn single_driver(&self) -> Option<&TokenStream> {
        match self {
            ProvidedDrivers::Single(driver) => Some(driver),
            _ => None,
        }
    }

    pub fn iter_for_checks(&self) -> ProvidedDriversIterator<'_> {
        match self {
            ProvidedDrivers::Single(_) => ProvidedDriversIterator::Single(self),
            ProvidedDrivers::SingleWithChecks { driver: _, checks } => {
                ProvidedDriversIterator::Multi {
                    iter: checks.iter(),
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers, conn: _ } => {
                ProvidedDriversIterator::Multi {
                    iter: drivers.iter(),
                }
            }
        }
    }

    pub fn arguments(&self, sql_crate: &TokenStream) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {driver.span()=>
                    #sql_crate::macro_support::DriverArguments::<#driver>::default()
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {conn.span()=>
                    #sql_crate::macro_support::args_for_driver(#conn)
                }
            }
        }
    }

    pub fn identifier_delimiter(&self, sql_crate: &TokenStream) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {driver.span()=>
                    <#driver as #sql_crate::Driver>::identifier_delimiter()
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {conn.span()=>
                    #sql_crate::macro_support::driver_identifier_delimiter(#conn)
                }
            }
        }
    }

    pub fn query_add_selected(
        &self,
        sql_crate: &TokenStream,
        output_type: &syn::Type,
        table_type: &syn::Type,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {output_type.span()=>
                    <#output_type as #sql_crate::Output<#table_type, #driver>>::select(&mut query);
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {output_type.span()=>
                    #sql_crate::macro_support::query_add_selected::<#table_type, #output_type, _>(
                        &mut query,
                        #conn,
                    );
                }
            }
        }
    }

    pub fn query_add_selected_with_args(
        &self,
        sql_crate: &TokenStream,
        table_type: &syn::Type,
        output_type: &syn::Type,
        output_arg_tokens: Vec<TokenStream>,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote! {
                    query.push_str(&<#output_type as #sql_crate::macro_support::OutputData<#table_type>>::SelectProvider::__easy_sql_select::<#driver>(
                        _easy_sql_d,
                        #(#output_arg_tokens),*
                    ));
                }
            }
            ProvidedDrivers::MultipleWithConn { conn, .. } => {
                quote! {
                    query.push_str(&<#output_type as #sql_crate::macro_support::OutputData<#table_type>>::SelectProvider::__easy_sql_select_driver_from_conn(
                        #conn,
                        _easy_sql_d,
                        #(#output_arg_tokens),*
                    ));
                }
            }
        }
    }

    pub fn query_insert_data(
        &self,
        sql_crate: &TokenStream,
        table_type: &syn::Type,
        to_insert: syn::Expr,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {to_insert.span()=>
                    #sql_crate::macro_support::query_insert_data_selected_driver::<#table_type, #driver, _>(
                        #[allow(unused_braces)]
                        {#to_insert},
                        _easy_sql_args,
                    )
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {to_insert.span()=>
                    #sql_crate::macro_support::query_insert_data::<#table_type, _, _>(
                        #[allow(unused_braces)]
                        {#to_insert},
                        _easy_sql_args,
                        #conn,
                    )
                }
            }
        }
    }

    pub fn query_update_data(
        &self,
        sql_crate: &TokenStream,
        table_type: &TokenStream,
        update_data: syn::Expr,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {update_data.span()=>
                    #sql_crate::macro_support::query_update_data_selected_driver::<#table_type, #driver, _>(
                        {#update_data},
                        _easy_sql_args,
                        &mut query,
                        &mut current_arg_n,
                    )
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {update_data.span()=>
                    #sql_crate::macro_support::query_update_data::<#table_type, _, _>(
                        #[allow(unused_braces)]
                        {#update_data},
                        _easy_sql_args,
                        &mut query,
                        &mut current_arg_n,
                        #conn,
                    )
                }
            }
        }
    }

    pub fn table_joins(&self, sql_crate: &TokenStream, table_type: &syn::Type) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {table_type.span()=>
                    <#table_type as #sql_crate::Table<#driver>>::table_joins(&mut query);
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {table_type.span()=>
                    #sql_crate::macro_support::driver_table_joins::<#table_type, _>(
                        &mut query,
                        #conn,
                    );
                }
            }
        }
    }

    pub fn parameter_placeholder_base(&self, sql_crate: &TokenStream) -> TokenStream {
        match self {
            ProvidedDrivers::Single(_) | ProvidedDrivers::SingleWithChecks { .. } => {
                quote! {}
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {conn.span()=>
                    let mut __easy_sql_parameter_placeholder =
                        #sql_crate::macro_support::driver_parameter_placeholder(#conn);
                }
            }
        }
    }

    pub fn parameter_placeholder_fn(
        &self,
        sql_crate: &TokenStream,
        quote_span: proc_macro2::Span,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {quote_span=>
                    <#driver as #sql_crate::Driver>::parameter_placeholder
                }
            }
            ProvidedDrivers::MultipleWithConn {
                drivers: _,
                conn: _,
            } => {
                quote_spanned! {quote_span=>
                    __easy_sql_parameter_placeholder
                }
            }
        }
    }

    pub fn parameter_placeholder(
        &self,
        sql_crate: &TokenStream,
        span: proc_macro2::Span,
        before_param_n: impl ToTokens,
        current_param_n: impl ToTokens,
    ) -> TokenStream {
        let pp_fn = self.parameter_placeholder_fn(sql_crate, span);
        quote_spanned! {span=>
            #pp_fn(#before_param_n #current_param_n)
        }
    }

    pub fn type_info(&self, sql_crate: &TokenStream, field_type: &syn::Type) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {field_type.span()=>
                    <#field_type as #sql_crate::macro_support::Type<
                        #sql_crate::macro_support::InternalDriver<#driver>
                    >>::type_info()
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {field_type.span()=>
                    #sql_crate::macro_support::driver_type_info::<#field_type, _>(#conn)
                }
            }
        }
    }

    pub fn table_name<T: ToTokens + Spanned>(
        &self,
        sql_crate: &TokenStream,
        table_type: &T,
    ) -> TokenStream {
        match self {
            ProvidedDrivers::Single(driver) | ProvidedDrivers::SingleWithChecks { driver, .. } => {
                quote_spanned! {table_type.span()=>
                    <#table_type as #sql_crate::Table<#driver>>::table_name()
                }
            }
            ProvidedDrivers::MultipleWithConn { drivers: _, conn } => {
                quote_spanned! {table_type.span()=>
                    #sql_crate::macro_support::driver_related_table_name::<#table_type,_>(#conn)
                }
            }
        }
    }
}

pub enum ProvidedDriversIterator<'a> {
    Done,
    Single(&'a ProvidedDrivers),
    Multi {
        iter: std::slice::Iter<'a, TokenStream>,
    },
}
impl<'a> Iterator for ProvidedDriversIterator<'a> {
    type Item = &'a TokenStream;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            ProvidedDriversIterator::Done => None,
            ProvidedDriversIterator::Single(provided) => {
                let result = match provided {
                    ProvidedDrivers::Single(driver) => Some(driver),
                    _ => unreachable!("Iterator in Single state but ProvidedDrivers is not Single"),
                };
                *self = ProvidedDriversIterator::Done;
                result
            }
            ProvidedDriversIterator::Multi { iter } => iter.next(),
        }
    }
}