bindable.rs

  1use std::{
  2    ffi::OsStr,
  3    os::unix::prelude::OsStrExt,
  4    path::{Path, PathBuf},
  5    sync::Arc,
  6};
  7
  8use anyhow::{Context, Result};
  9
 10use crate::statement::{SqlType, Statement};
 11
 12pub trait Bind {
 13    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32>;
 14}
 15
 16pub trait Column: Sized {
 17    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)>;
 18}
 19
 20impl Bind for bool {
 21    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 22        statement
 23            .bind(self.then_some(1).unwrap_or(0), start_index)
 24            .with_context(|| format!("Failed to bind bool at index {start_index}"))
 25    }
 26}
 27
 28impl Column for bool {
 29    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
 30        i32::column(statement, start_index)
 31            .map(|(i, next_index)| (i != 0, next_index))
 32            .with_context(|| format!("Failed to read bool at index {start_index}"))
 33    }
 34}
 35
 36impl Bind for &[u8] {
 37    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 38        statement
 39            .bind_blob(start_index, self)
 40            .with_context(|| format!("Failed to bind &[u8] at index {start_index}"))?;
 41        Ok(start_index + 1)
 42    }
 43}
 44
 45impl<const C: usize> Bind for &[u8; C] {
 46    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 47        statement
 48            .bind_blob(start_index, self.as_slice())
 49            .with_context(|| format!("Failed to bind &[u8; C] at index {start_index}"))?;
 50        Ok(start_index + 1)
 51    }
 52}
 53
 54impl Bind for Vec<u8> {
 55    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 56        statement
 57            .bind_blob(start_index, self)
 58            .with_context(|| format!("Failed to bind Vec<u8> at index {start_index}"))?;
 59        Ok(start_index + 1)
 60    }
 61}
 62
 63impl Column for Vec<u8> {
 64    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
 65        let result = statement
 66            .column_blob(start_index)
 67            .with_context(|| format!("Failed to read Vec<u8> at index {start_index}"))?;
 68
 69        Ok((Vec::from(result), start_index + 1))
 70    }
 71}
 72
 73impl Bind for f64 {
 74    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 75        statement
 76            .bind_double(start_index, *self)
 77            .with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
 78        Ok(start_index + 1)
 79    }
 80}
 81
 82impl Column for f64 {
 83    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
 84        let result = statement
 85            .column_double(start_index)
 86            .with_context(|| format!("Failed to parse f64 at index {start_index}"))?;
 87
 88        Ok((result, start_index + 1))
 89    }
 90}
 91
 92impl Bind for i32 {
 93    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
 94        statement
 95            .bind_int(start_index, *self)
 96            .with_context(|| format!("Failed to bind i32 at index {start_index}"))?;
 97
 98        Ok(start_index + 1)
 99    }
100}
101
102impl Column for i32 {
103    fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
104        let result = statement.column_int(start_index)?;
105        Ok((result, start_index + 1))
106    }
107}
108
109impl Bind for i64 {
110    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
111        statement
112            .bind_int64(start_index, *self)
113            .with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
114        Ok(start_index + 1)
115    }
116}
117
118impl Column for i64 {
119    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
120        let result = statement.column_int64(start_index)?;
121        Ok((result, start_index + 1))
122    }
123}
124
125impl Bind for usize {
126    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
127        (*self as i64)
128            .bind(statement, start_index)
129            .with_context(|| format!("Failed to bind usize at index {start_index}"))
130    }
131}
132
133impl Column for usize {
134    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
135        let result = statement.column_int64(start_index)?;
136        Ok((result as usize, start_index + 1))
137    }
138}
139
140impl Bind for () {
141    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
142        statement.bind_null(start_index)?;
143        Ok(start_index + 1)
144    }
145}
146
147impl Bind for &str {
148    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
149        statement.bind_text(start_index, self)?;
150        Ok(start_index + 1)
151    }
152}
153
154impl Bind for Arc<str> {
155    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
156        statement.bind_text(start_index, self.as_ref())?;
157        Ok(start_index + 1)
158    }
159}
160
161impl Bind for String {
162    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
163        statement.bind_text(start_index, self)?;
164        Ok(start_index + 1)
165    }
166}
167
168impl Column for Arc<str> {
169    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
170        let result = statement.column_text(start_index)?;
171        Ok((Arc::from(result), start_index + 1))
172    }
173}
174
175impl Column for String {
176    fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
177        let result = statement.column_text(start_index)?;
178        Ok((result.to_owned(), start_index + 1))
179    }
180}
181
182impl<T1: Bind, T2: Bind> Bind for (T1, T2) {
183    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
184        let next_index = self.0.bind(statement, start_index)?;
185        self.1.bind(statement, next_index)
186    }
187}
188
189impl<T1: Column, T2: Column> Column for (T1, T2) {
190    fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
191        let (first, next_index) = T1::column(statement, start_index)?;
192        let (second, next_index) = T2::column(statement, next_index)?;
193        Ok(((first, second), next_index))
194    }
195}
196
197impl<T1: Bind, T2: Bind, T3: Bind> Bind for (T1, T2, T3) {
198    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
199        let next_index = self.0.bind(statement, start_index)?;
200        let next_index = self.1.bind(statement, next_index)?;
201        self.2.bind(statement, next_index)
202    }
203}
204
205impl<T1: Column, T2: Column, T3: Column> Column for (T1, T2, T3) {
206    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
207        let (first, next_index) = T1::column(statement, start_index)?;
208        let (second, next_index) = T2::column(statement, next_index)?;
209        let (third, next_index) = T3::column(statement, next_index)?;
210        Ok(((first, second, third), next_index))
211    }
212}
213
214impl<T1: Bind, T2: Bind, T3: Bind, T4: Bind> Bind for (T1, T2, T3, T4) {
215    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
216        let next_index = self.0.bind(statement, start_index)?;
217        let next_index = self.1.bind(statement, next_index)?;
218        let next_index = self.2.bind(statement, next_index)?;
219        self.3.bind(statement, next_index)
220    }
221}
222
223impl<T1: Column, T2: Column, T3: Column, T4: Column> Column for (T1, T2, T3, T4) {
224    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
225        let (first, next_index) = T1::column(statement, start_index)?;
226        let (second, next_index) = T2::column(statement, next_index)?;
227        let (third, next_index) = T3::column(statement, next_index)?;
228        let (fourth, next_index) = T4::column(statement, next_index)?;
229        Ok(((first, second, third, fourth), next_index))
230    }
231}
232
233impl<T1: Bind, T2: Bind, T3: Bind, T4: Bind, T5: Bind> Bind for (T1, T2, T3, T4, T5) {
234    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
235        let next_index = self.0.bind(statement, start_index)?;
236        let next_index = self.1.bind(statement, next_index)?;
237        let next_index = self.2.bind(statement, next_index)?;
238        let next_index = self.3.bind(statement, next_index)?;
239        self.4.bind(statement, next_index)
240    }
241}
242
243impl<T1: Column, T2: Column, T3: Column, T4: Column, T5: Column> Column for (T1, T2, T3, T4, T5) {
244    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
245        let (first, next_index) = T1::column(statement, start_index)?;
246        let (second, next_index) = T2::column(statement, next_index)?;
247        let (third, next_index) = T3::column(statement, next_index)?;
248        let (fourth, next_index) = T4::column(statement, next_index)?;
249        let (fifth, next_index) = T5::column(statement, next_index)?;
250        Ok(((first, second, third, fourth, fifth), next_index))
251    }
252}
253
254impl<T: Bind> Bind for Option<T> {
255    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
256        if let Some(this) = self {
257            this.bind(statement, start_index)
258        } else {
259            statement.bind_null(start_index)?;
260            Ok(start_index + 1)
261        }
262    }
263}
264
265impl<T: Column> Column for Option<T> {
266    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
267        if let SqlType::Null = statement.column_type(start_index)? {
268            Ok((None, start_index + 1))
269        } else {
270            T::column(statement, start_index).map(|(result, next_index)| (Some(result), next_index))
271        }
272    }
273}
274
275impl<T: Bind, const COUNT: usize> Bind for [T; COUNT] {
276    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
277        let mut current_index = start_index;
278        for binding in self {
279            current_index = binding.bind(statement, current_index)?
280        }
281
282        Ok(current_index)
283    }
284}
285
286impl<T: Column + Default + Copy, const COUNT: usize> Column for [T; COUNT] {
287    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
288        let mut array = [Default::default(); COUNT];
289        let mut current_index = start_index;
290        for i in 0..COUNT {
291            (array[i], current_index) = T::column(statement, current_index)?;
292        }
293        Ok((array, current_index))
294    }
295}
296
297impl<T: Bind> Bind for Vec<T> {
298    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
299        let mut current_index = start_index;
300        for binding in self.iter() {
301            current_index = binding.bind(statement, current_index)?
302        }
303
304        Ok(current_index)
305    }
306}
307
308impl<T: Bind> Bind for &[T] {
309    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
310        let mut current_index = start_index;
311        for binding in *self {
312            current_index = binding.bind(statement, current_index)?
313        }
314
315        Ok(current_index)
316    }
317}
318
319impl Bind for &Path {
320    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
321        self.as_os_str().as_bytes().bind(statement, start_index)
322    }
323}
324
325impl Bind for Arc<Path> {
326    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
327        self.as_ref().bind(statement, start_index)
328    }
329}
330
331impl Bind for PathBuf {
332    fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
333        (self.as_ref() as &Path).bind(statement, start_index)
334    }
335}
336
337impl Column for PathBuf {
338    fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
339        let blob = statement.column_blob(start_index)?;
340
341        Ok((
342            PathBuf::from(OsStr::from_bytes(blob).to_owned()),
343            start_index + 1,
344        ))
345    }
346}