use tokio_postgres::types::ToSql;

enum BorrowedOrBoxed<'a, T: ?Sized> {
    Borrowed(&'a T),
    Boxed(Box<T>),
}

pub struct QueryBindings<'a>(Vec<BorrowedOrBoxed<'a, dyn 'a + Sync + ToSql>>);

impl<'a> QueryBindings<'a> {
    pub fn new() -> Self {
        return QueryBindings(Vec::with_capacity(8));
    }

    pub fn add(&mut self, arg: &'a (dyn Sync + ToSql)) -> usize {
        self.0.push(BorrowedOrBoxed::Borrowed(arg));

        return self.0.len();
    }

    pub fn add_boxed(&mut self, arg: Box<dyn 'a + Sync + ToSql>) -> usize {
        self.0.push(BorrowedOrBoxed::Boxed(arg));

        return self.0.len();
    }

    pub fn to_params(&self) -> Vec<&(dyn Sync + ToSql)> {
        return self
            .0
            .iter()
            .map(|it| match &it {
                BorrowedOrBoxed::Boxed(x) => &**x,
                BorrowedOrBoxed::Borrowed(x) => *x,
            })
            .collect();
    }
}
