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<'q>>>,
encode_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),
encode_placeholder_fn: None,
data: d,
}
}
pub fn set_encode_placeholder_fn(&mut self, f: fn(usize, &mut String)) {
self.encode_placeholder_fn = Some(f);
}
pub fn e<ImplEncode>(&self, t: ImplEncode) -> String
where
ImplEncode: Encode<'q, DB> + Type<DB> + 'q,
{
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.encode_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<ImplEncode>(&self, args: impl ::std::iter::IntoIterator<Item = ImplEncode>) -> String
where
ImplEncode: Encode<'q, DB> + Type<DB> + 'q,
{
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 et<ImplEncode>(&self, t: &ImplEncode) -> ::std::string::String
where
ImplEncode: Encode<'q, DB> + Type<DB> + ::std::clone::Clone + 'q,
{
self.e(t.clone())
}
pub fn etl<'arg_b, ImplEncode>(
&self,
args: impl ::std::iter::IntoIterator<Item = &'arg_b ImplEncode>,
) -> ::std::string::String
where
'q: 'arg_b,
ImplEncode: Encode<'q, DB> + Type<DB> + ::std::clone::Clone + 'q,
{
let args = args.into_iter().cloned();
self.el(args)
}
pub fn get_err(&self) -> Option<Error> {
self.error.borrow_mut().take()
}
pub fn get_arguments(&self) -> Option<DB::Arguments<'q>> {
self.arguments.borrow_mut().take()
}
}
impl<'q, DB: Database, D> Deref for TemplateArg<'q, DB, D> {
type Target = &'q D;
fn deref(&self) -> &Self::Target {
&self.data
}
}