1use std::{
2 path::{Path, PathBuf},
3 sync::Arc,
4};
5
6use anyhow::{Context as _, Result};
7use util::paths::PathExt;
8
9use crate::statement::{SqlType, Statement};
10
11pub trait StaticColumnCount {
12 fn column_count() -> usize {
13 1
14 }
15}
16
17pub trait Bind {
18 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32>;
19}
20
21pub trait Column: Sized {
22 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)>;
23}
24
25impl StaticColumnCount for bool {}
26impl Bind for bool {
27 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
28 statement
29 .bind(&self.then_some(1).unwrap_or(0), start_index)
30 .with_context(|| format!("Failed to bind bool at index {start_index}"))
31 }
32}
33
34impl Column for bool {
35 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
36 i32::column(statement, start_index)
37 .map(|(i, next_index)| (i != 0, next_index))
38 .with_context(|| format!("Failed to read bool at index {start_index}"))
39 }
40}
41
42impl StaticColumnCount for &[u8] {}
43impl Bind for &[u8] {
44 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
45 statement
46 .bind_blob(start_index, self)
47 .with_context(|| format!("Failed to bind &[u8] at index {start_index}"))?;
48 Ok(start_index + 1)
49 }
50}
51
52impl<const C: usize> StaticColumnCount for &[u8; C] {}
53impl<const C: usize> Bind for &[u8; C] {
54 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
55 statement
56 .bind_blob(start_index, self.as_slice())
57 .with_context(|| format!("Failed to bind &[u8; C] at index {start_index}"))?;
58 Ok(start_index + 1)
59 }
60}
61
62impl<const C: usize> Column for [u8; C] {
63 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
64 let bytes_slice = statement.column_blob(start_index)?;
65 let array = bytes_slice.try_into()?;
66 Ok((array, start_index + 1))
67 }
68}
69
70impl StaticColumnCount for Vec<u8> {}
71impl Bind for Vec<u8> {
72 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
73 statement
74 .bind_blob(start_index, self)
75 .with_context(|| format!("Failed to bind Vec<u8> at index {start_index}"))?;
76 Ok(start_index + 1)
77 }
78}
79
80impl Column for Vec<u8> {
81 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
82 let result = statement
83 .column_blob(start_index)
84 .with_context(|| format!("Failed to read Vec<u8> at index {start_index}"))?;
85
86 Ok((Vec::from(result), start_index + 1))
87 }
88}
89
90impl StaticColumnCount for f64 {}
91impl Bind for f64 {
92 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
93 statement
94 .bind_double(start_index, *self)
95 .with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
96 Ok(start_index + 1)
97 }
98}
99
100impl Column for f64 {
101 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
102 let result = statement
103 .column_double(start_index)
104 .with_context(|| format!("Failed to parse f64 at index {start_index}"))?;
105
106 Ok((result, start_index + 1))
107 }
108}
109
110impl StaticColumnCount for f32 {}
111impl Bind for f32 {
112 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
113 statement
114 .bind_double(start_index, *self as f64)
115 .with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
116 Ok(start_index + 1)
117 }
118}
119
120impl Column for f32 {
121 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
122 let result = statement
123 .column_double(start_index)
124 .with_context(|| format!("Failed to parse f32 at index {start_index}"))?
125 as f32;
126
127 Ok((result, start_index + 1))
128 }
129}
130
131impl StaticColumnCount for i32 {}
132impl Bind for i32 {
133 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
134 statement
135 .bind_int(start_index, *self)
136 .with_context(|| format!("Failed to bind i32 at index {start_index}"))?;
137
138 Ok(start_index + 1)
139 }
140}
141
142impl Column for i32 {
143 fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
144 let result = statement.column_int(start_index)?;
145 Ok((result, start_index + 1))
146 }
147}
148
149impl StaticColumnCount for i64 {}
150impl Bind for i64 {
151 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
152 statement
153 .bind_int64(start_index, *self)
154 .with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
155 Ok(start_index + 1)
156 }
157}
158
159impl Column for i64 {
160 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
161 let result = statement.column_int64(start_index)?;
162 Ok((result, start_index + 1))
163 }
164}
165
166impl StaticColumnCount for u64 {}
167impl Bind for u64 {
168 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
169 statement
170 .bind_int64(start_index, (*self) as i64)
171 .with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
172 Ok(start_index + 1)
173 }
174}
175
176impl Column for u64 {
177 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
178 let result = statement.column_int64(start_index)? as u64;
179 Ok((result, start_index + 1))
180 }
181}
182
183impl StaticColumnCount for u32 {}
184impl Bind for u32 {
185 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
186 (*self as i64)
187 .bind(statement, start_index)
188 .with_context(|| format!("Failed to bind usize at index {start_index}"))
189 }
190}
191
192impl Column for u32 {
193 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
194 let result = statement.column_int64(start_index)?;
195 Ok((result as u32, start_index + 1))
196 }
197}
198
199impl StaticColumnCount for u16 {}
200impl Bind for u16 {
201 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
202 (*self as i64)
203 .bind(statement, start_index)
204 .with_context(|| format!("Failed to bind usize at index {start_index}"))
205 }
206}
207
208impl Column for u16 {
209 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
210 let result = statement.column_int64(start_index)?;
211 Ok((result as u16, start_index + 1))
212 }
213}
214
215impl StaticColumnCount for usize {}
216impl Bind for usize {
217 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
218 (*self as i64)
219 .bind(statement, start_index)
220 .with_context(|| format!("Failed to bind usize at index {start_index}"))
221 }
222}
223
224impl Column for usize {
225 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
226 let result = statement.column_int64(start_index)?;
227 Ok((result as usize, start_index + 1))
228 }
229}
230
231impl StaticColumnCount for &str {}
232impl Bind for &str {
233 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
234 statement.bind_text(start_index, self)?;
235 Ok(start_index + 1)
236 }
237}
238
239impl StaticColumnCount for Arc<str> {}
240impl Bind for Arc<str> {
241 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
242 statement.bind_text(start_index, self.as_ref())?;
243 Ok(start_index + 1)
244 }
245}
246
247impl StaticColumnCount for String {}
248impl Bind for String {
249 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
250 statement.bind_text(start_index, self)?;
251 Ok(start_index + 1)
252 }
253}
254
255impl Column for Arc<str> {
256 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
257 let result = statement.column_text(start_index)?;
258 Ok((Arc::from(result), start_index + 1))
259 }
260}
261
262impl Column for String {
263 fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
264 let result = statement.column_text(start_index)?;
265 Ok((result.to_owned(), start_index + 1))
266 }
267}
268
269impl<T: StaticColumnCount> StaticColumnCount for Option<T> {
270 fn column_count() -> usize {
271 T::column_count()
272 }
273}
274impl<T: Bind + StaticColumnCount> Bind for Option<T> {
275 fn bind(&self, statement: &Statement, mut start_index: i32) -> Result<i32> {
276 if let Some(this) = self {
277 this.bind(statement, start_index)
278 } else {
279 for _ in 0..T::column_count() {
280 statement.bind_null(start_index)?;
281 start_index += 1;
282 }
283 Ok(start_index)
284 }
285 }
286}
287
288impl<T: Column + StaticColumnCount> Column for Option<T> {
289 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
290 if let SqlType::Null = statement.column_type(start_index)? {
291 Ok((None, start_index + T::column_count() as i32))
292 } else {
293 T::column(statement, start_index).map(|(result, next_index)| (Some(result), next_index))
294 }
295 }
296}
297
298impl<T: StaticColumnCount, const COUNT: usize> StaticColumnCount for [T; COUNT] {
299 fn column_count() -> usize {
300 T::column_count() * COUNT
301 }
302}
303impl<T: Bind, const COUNT: usize> Bind for [T; COUNT] {
304 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
305 let mut current_index = start_index;
306 for binding in self {
307 current_index = binding.bind(statement, current_index)?
308 }
309
310 Ok(current_index)
311 }
312}
313
314impl StaticColumnCount for &Path {}
315impl Bind for &Path {
316 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
317 self.as_os_str()
318 .as_encoded_bytes()
319 .bind(statement, start_index)
320 }
321}
322
323impl StaticColumnCount for Arc<Path> {}
324impl Bind for Arc<Path> {
325 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
326 self.as_ref().bind(statement, start_index)
327 }
328}
329impl Column for Arc<Path> {
330 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
331 let blob = statement.column_blob(start_index)?;
332
333 PathBuf::try_from_bytes(blob).map(|path| (Arc::from(path.as_path()), start_index + 1))
334 }
335}
336
337impl StaticColumnCount for PathBuf {}
338impl Bind for PathBuf {
339 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
340 (self.as_ref() as &Path).bind(statement, start_index)
341 }
342}
343
344impl Column for PathBuf {
345 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
346 let blob = statement.column_blob(start_index)?;
347
348 PathBuf::try_from_bytes(blob).map(|path| (path, start_index + 1))
349 }
350}
351
352impl StaticColumnCount for uuid::Uuid {
353 fn column_count() -> usize {
354 1
355 }
356}
357
358impl Bind for uuid::Uuid {
359 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
360 self.as_bytes().bind(statement, start_index)
361 }
362}
363
364impl Column for uuid::Uuid {
365 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
366 let (bytes, next_index) = Column::column(statement, start_index)?;
367 Ok((uuid::Uuid::from_bytes(bytes), next_index))
368 }
369}
370
371impl StaticColumnCount for () {
372 fn column_count() -> usize {
373 0
374 }
375}
376/// Unit impls do nothing. This simplifies query macros
377impl Bind for () {
378 fn bind(&self, _statement: &Statement, start_index: i32) -> Result<i32> {
379 Ok(start_index)
380 }
381}
382
383impl Column for () {
384 fn column(_statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
385 Ok(((), start_index))
386 }
387}
388
389macro_rules! impl_tuple_row_traits {
390 ( $($local:ident: $type:ident),+ ) => {
391 impl<$($type: StaticColumnCount),+> StaticColumnCount for ($($type,)+) {
392 fn column_count() -> usize {
393 let mut count = 0;
394 $(count += $type::column_count();)+
395 count
396 }
397 }
398
399 impl<$($type: Bind),+> Bind for ($($type,)+) {
400 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
401 let mut next_index = start_index;
402 let ($($local,)+) = self;
403 $(next_index = $local.bind(statement, next_index)?;)+
404 Ok(next_index)
405 }
406 }
407
408 impl<$($type: Column),+> Column for ($($type,)+) {
409 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
410 let mut next_index = start_index;
411 Ok((
412 (
413 $({
414 let value;
415 (value, next_index) = $type::column(statement, next_index)?;
416 value
417 },)+
418 ),
419 next_index,
420 ))
421 }
422 }
423 }
424}
425
426impl_tuple_row_traits!(t1: T1, t2: T2);
427impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3);
428impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4);
429impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5);
430impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6);
431impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7);
432impl_tuple_row_traits!(
433 t1: T1,
434 t2: T2,
435 t3: T3,
436 t4: T4,
437 t5: T5,
438 t6: T6,
439 t7: T7,
440 t8: T8
441);
442impl_tuple_row_traits!(
443 t1: T1,
444 t2: T2,
445 t3: T3,
446 t4: T4,
447 t5: T5,
448 t6: T6,
449 t7: T7,
450 t8: T8,
451 t9: T9
452);
453impl_tuple_row_traits!(
454 t1: T1,
455 t2: T2,
456 t3: T3,
457 t4: T4,
458 t5: T5,
459 t6: T6,
460 t7: T7,
461 t8: T8,
462 t9: T9,
463 t10: T10
464);