use crate::prelude::*;
use proc_macro2::Span;
pub struct DefaultExpr {
is_string: bool,
expr: String,
}
impl ToTokens for DefaultExpr {
fn to_tokens(&self, tokens: &mut TokenStream2) {
if !self.is_string {
let expr = &self.expr;
tokens.extend(quote!(#expr));
} else {
let sql_snippet = format!("'{}'", self.expr);
let lit_str = syn::LitStr::new(&sql_snippet, proc_macro2::Span::call_site());
tokens.extend(quote!(#lit_str));
}
}
}
impl Parse for DefaultExpr {
fn parse(input: parse::ParseStream) -> Result<Self> {
use sql_from_models_parser::{dialect::*, parser::Parser, tokenizer::*};
let span = Span::call_site();
let mut is_string = false;
let expr = match input.parse::<Lit>() {
Ok(Lit::Bool(boolean)) => boolean.value().to_string(),
Ok(Lit::Int(int)) => int.to_string(),
Ok(Lit::Float(float)) => float.to_string(),
Ok(Lit::Str(string)) => {
is_string = true;
string.value() }
Ok(_) | Err(_) => {
return Err(Error::new(
input.span(),
"Expected string, boolean, or numeric literal"
));
}
};
let expr_for_parser = if is_string && expr.is_empty() {
"''"
} else {
&expr
};
let mut lexer = Tokenizer::new(&GenericDialect {}, expr_for_parser);
let tokens = lexer.tokenize().map_err(|err| {
syn::Error::new(span, format!("Failed to tokenize default expression: {:?}", err))
})?;
Parser::new(tokens, &GenericDialect {})
.parse_expr()
.map_err(|err| {
syn::Error::new(span, format!("Failed to parse default expression: {}", err))
})?;
Ok(DefaultExpr { is_string, expr })
}
}