use std::{cell::RefCell, ops::Deref};
use sqlx_core::{Error, arguments::Arguments, database::Database, encode::Encode, types::Type};
pub struct TemplateArg<'q, DB: Database, D> {
error: RefCell<Option<Error>>,
arguments: RefCell<Option<DB::Arguments>>,
format_placeholder_fn: Option<fn(usize, &mut String)>,
data: &'q D,
}
impl<'q, DB: Database, D> TemplateArg<'q, DB, D> {
pub fn new(d: &'q D) -> Self {
TemplateArg {
error: RefCell::new(None),
arguments: RefCell::new(None),
format_placeholder_fn: None,
data: d,
}
}
pub fn set_format_placeholder_fn(&mut self, format_placeholder: fn(usize, &mut String)) {
self.format_placeholder_fn = Some(format_placeholder);
}
pub fn e<'t, ImplEncode>(&self, t: ImplEncode) -> String
where
ImplEncode: Encode<'t, DB> + Type<DB>,
{
let mut arguments = self.arguments.borrow_mut().take().unwrap_or_default();
let mut err = self.error.borrow_mut();
if let Err(encode_err) = arguments.add(t)
&& err.is_none()
{
*err = Some(Error::Encode(encode_err));
}
let mut placeholder = String::new();
if let Some(encode_placeholder_fn) = &self.format_placeholder_fn {
encode_placeholder_fn(arguments.len(), &mut placeholder);
} else if let Err(e) = arguments.format_placeholder(&mut placeholder) {
*err = Some(Error::Encode(Box::new(e)));
}
*self.arguments.borrow_mut() = Some(arguments);
placeholder
}
pub fn el<'t, ImplEncode>(
&self,
args: impl ::std::iter::IntoIterator<Item = ImplEncode>,
) -> String
where
ImplEncode: Encode<'t, DB> + Type<DB>,
{
let mut placeholder = String::new();
placeholder.push('(');
for arg in args {
placeholder.push_str(&self.e(arg));
placeholder.push(',');
}
if placeholder.ends_with(",") {
placeholder.pop();
}
placeholder.push(')');
placeholder
}
pub fn get_err(&self) -> Option<Error> {
self.error.borrow_mut().take()
}
pub fn get_arguments(&self) -> Option<DB::Arguments> {
self.arguments.borrow_mut().take()
}
}
impl<'t, DB: Database, D> Deref for TemplateArg<'t, DB, D> {
type Target = &'t D;
fn deref(&self) -> &Self::Target {
&self.data
}
}