1use drizzle_core::error::DrizzleError;
7use std::{rc::Rc, sync::Arc};
8
9pub trait FromSQLiteValue: Sized {
20 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError>;
22
23 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError>;
25
26 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError>;
28
29 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError>;
31
32 fn from_sqlite_null() -> Result<Self, DrizzleError> {
34 Err(DrizzleError::ConversionError(
35 "unexpected NULL value".into(),
36 ))
37 }
38
39 #[cfg(feature = "rusqlite")]
41 fn from_value_ref(value: ::rusqlite::types::ValueRef<'_>) -> Result<Self, DrizzleError> {
42 match value {
43 ::rusqlite::types::ValueRef::Null => Self::from_sqlite_null(),
44 ::rusqlite::types::ValueRef::Integer(i) => Self::from_sqlite_integer(i),
45 ::rusqlite::types::ValueRef::Real(r) => Self::from_sqlite_real(r),
46 ::rusqlite::types::ValueRef::Text(text) => {
47 let s = std::str::from_utf8(text).map_err(|e| {
48 DrizzleError::ConversionError(format!("invalid UTF-8: {}", e).into())
49 })?;
50 Self::from_sqlite_text(s)
51 }
52 ::rusqlite::types::ValueRef::Blob(blob) => Self::from_sqlite_blob(blob),
53 }
54 }
55}
56
57pub trait DrizzleRowByIndex {
59 fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError>;
61}
62
63pub trait DrizzleRowByName: DrizzleRowByIndex {
65 fn get_column_by_name<T: FromSQLiteValue>(&self, name: &str) -> Result<T, DrizzleError>;
67}
68
69fn checked_real_to_int<T>(value: f64, type_name: &str) -> Result<T, DrizzleError>
70where
71 T: TryFrom<i128>,
72 <T as TryFrom<i128>>::Error: core::fmt::Display,
73{
74 if !value.is_finite() {
75 return Err(DrizzleError::ConversionError(
76 format!("cannot convert non-finite REAL {} to {}", value, type_name).into(),
77 ));
78 }
79
80 if value.fract() != 0.0 {
81 return Err(DrizzleError::ConversionError(
82 format!("cannot convert non-integer REAL {} to {}", value, type_name).into(),
83 ));
84 }
85
86 if value < i128::MIN as f64 || value > i128::MAX as f64 {
87 return Err(DrizzleError::ConversionError(
88 format!("REAL {} out of range for {}", value, type_name).into(),
89 ));
90 }
91
92 let int_value = value as i128;
93 int_value.try_into().map_err(|e| {
94 DrizzleError::ConversionError(
95 format!("REAL {} out of range for {}: {}", value, type_name, e).into(),
96 )
97 })
98}
99
100macro_rules! impl_from_sqlite_value_int {
106 (i64) => {
108 impl FromSQLiteValue for i64 {
109 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
110 Ok(value)
111 }
112
113 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
114 value.parse().map_err(|e| {
115 DrizzleError::ConversionError(format!("cannot parse '{}' as i64: {}", value, e).into())
116 })
117 }
118
119 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
120 checked_real_to_int(value, "i64")
121 }
122
123 fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
124 Err(DrizzleError::ConversionError("cannot convert BLOB to i64".into()))
125 }
126 }
127 };
128 ($($ty:ty),+ $(,)?) => {
130 $(
131 impl FromSQLiteValue for $ty {
132 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
133 value.try_into().map_err(|e| {
134 DrizzleError::ConversionError(
135 format!("i64 {} out of range for {}: {}", value, stringify!($ty), e).into(),
136 )
137 })
138 }
139
140 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
141 value.parse().map_err(|e| {
142 DrizzleError::ConversionError(
143 format!("cannot parse '{}' as {}: {}", value, stringify!($ty), e).into()
144 )
145 })
146 }
147
148 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
149 checked_real_to_int(value, stringify!($ty))
150 }
151
152 fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
153 Err(DrizzleError::ConversionError(
154 concat!("cannot convert BLOB to ", stringify!($ty)).into()
155 ))
156 }
157 }
158 )+
159 };
160}
161
162macro_rules! impl_from_sqlite_value_float {
164 ($($ty:ty),+ $(,)?) => {
165 $(
166 impl FromSQLiteValue for $ty {
167 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
168 Ok(value as $ty)
169 }
170
171 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
172 value.parse().map_err(|e| {
173 DrizzleError::ConversionError(
174 format!("cannot parse '{}' as {}: {}", value, stringify!($ty), e).into()
175 )
176 })
177 }
178
179 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
180 Ok(value as $ty)
181 }
182
183 fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
184 Err(DrizzleError::ConversionError(
185 concat!("cannot convert BLOB to ", stringify!($ty)).into()
186 ))
187 }
188 }
189 )+
190 };
191}
192
193impl_from_sqlite_value_int!(i64);
195impl_from_sqlite_value_int!(i8, i16, i32, isize, u8, u16, u32, u64, usize);
196
197impl_from_sqlite_value_float!(f32, f64);
199
200impl FromSQLiteValue for bool {
201 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
202 Ok(value != 0)
203 }
204
205 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
206 match value.to_lowercase().as_str() {
207 "true" | "1" | "yes" | "on" => Ok(true),
208 "false" | "0" | "no" | "off" => Ok(false),
209 _ => Err(DrizzleError::ConversionError(
210 format!("cannot parse '{}' as bool", value).into(),
211 )),
212 }
213 }
214
215 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
216 Ok(value != 0.0)
217 }
218
219 fn from_sqlite_blob(_value: &[u8]) -> Result<Self, DrizzleError> {
220 Err(DrizzleError::ConversionError(
221 "cannot convert BLOB to bool".into(),
222 ))
223 }
224}
225
226impl FromSQLiteValue for String {
227 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
228 Ok(value.to_string())
229 }
230
231 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
232 Ok(value.to_string())
233 }
234
235 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
236 Ok(value.to_string())
237 }
238
239 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
240 String::from_utf8(value.to_vec()).map_err(|e| {
241 DrizzleError::ConversionError(format!("invalid UTF-8 in BLOB: {}", e).into())
242 })
243 }
244}
245
246impl FromSQLiteValue for Box<String> {
247 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
248 String::from_sqlite_integer(value).map(Box::new)
249 }
250
251 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
252 String::from_sqlite_text(value).map(Box::new)
253 }
254
255 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
256 String::from_sqlite_real(value).map(Box::new)
257 }
258
259 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
260 String::from_sqlite_blob(value).map(Box::new)
261 }
262}
263
264impl FromSQLiteValue for Rc<String> {
265 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
266 String::from_sqlite_integer(value).map(Rc::new)
267 }
268
269 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
270 String::from_sqlite_text(value).map(Rc::new)
271 }
272
273 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
274 String::from_sqlite_real(value).map(Rc::new)
275 }
276
277 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
278 String::from_sqlite_blob(value).map(Rc::new)
279 }
280}
281
282impl FromSQLiteValue for Arc<String> {
283 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
284 String::from_sqlite_integer(value).map(Arc::new)
285 }
286
287 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
288 String::from_sqlite_text(value).map(Arc::new)
289 }
290
291 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
292 String::from_sqlite_real(value).map(Arc::new)
293 }
294
295 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
296 String::from_sqlite_blob(value).map(Arc::new)
297 }
298}
299
300impl FromSQLiteValue for Box<str> {
301 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
302 String::from_sqlite_integer(value).map(String::into_boxed_str)
303 }
304
305 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
306 String::from_sqlite_text(value).map(String::into_boxed_str)
307 }
308
309 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
310 String::from_sqlite_real(value).map(String::into_boxed_str)
311 }
312
313 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
314 String::from_sqlite_blob(value).map(String::into_boxed_str)
315 }
316}
317
318impl FromSQLiteValue for Rc<str> {
319 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
320 String::from_sqlite_integer(value).map(Rc::from)
321 }
322
323 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
324 String::from_sqlite_text(value).map(Rc::from)
325 }
326
327 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
328 String::from_sqlite_real(value).map(Rc::from)
329 }
330
331 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
332 String::from_sqlite_blob(value).map(Rc::from)
333 }
334}
335
336impl FromSQLiteValue for Arc<str> {
337 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
338 String::from_sqlite_integer(value).map(Arc::from)
339 }
340
341 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
342 String::from_sqlite_text(value).map(Arc::from)
343 }
344
345 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
346 String::from_sqlite_real(value).map(Arc::from)
347 }
348
349 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
350 String::from_sqlite_blob(value).map(Arc::from)
351 }
352}
353
354impl FromSQLiteValue for Vec<u8> {
355 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
356 Ok(value.to_le_bytes().to_vec())
357 }
358
359 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
360 Ok(value.as_bytes().to_vec())
361 }
362
363 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
364 Ok(value.to_le_bytes().to_vec())
365 }
366
367 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
368 Ok(value.to_vec())
369 }
370}
371
372impl FromSQLiteValue for Box<Vec<u8>> {
373 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
374 Vec::<u8>::from_sqlite_integer(value).map(Box::new)
375 }
376
377 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
378 Vec::<u8>::from_sqlite_text(value).map(Box::new)
379 }
380
381 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
382 Vec::<u8>::from_sqlite_real(value).map(Box::new)
383 }
384
385 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
386 Vec::<u8>::from_sqlite_blob(value).map(Box::new)
387 }
388}
389
390impl FromSQLiteValue for Rc<Vec<u8>> {
391 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
392 Vec::<u8>::from_sqlite_integer(value).map(Rc::new)
393 }
394
395 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
396 Vec::<u8>::from_sqlite_text(value).map(Rc::new)
397 }
398
399 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
400 Vec::<u8>::from_sqlite_real(value).map(Rc::new)
401 }
402
403 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
404 Vec::<u8>::from_sqlite_blob(value).map(Rc::new)
405 }
406}
407
408impl FromSQLiteValue for Arc<Vec<u8>> {
409 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
410 Vec::<u8>::from_sqlite_integer(value).map(Arc::new)
411 }
412
413 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
414 Vec::<u8>::from_sqlite_text(value).map(Arc::new)
415 }
416
417 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
418 Vec::<u8>::from_sqlite_real(value).map(Arc::new)
419 }
420
421 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
422 Vec::<u8>::from_sqlite_blob(value).map(Arc::new)
423 }
424}
425
426impl<T: FromSQLiteValue> FromSQLiteValue for Option<T> {
428 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
429 T::from_sqlite_integer(value).map(Some)
430 }
431
432 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
433 T::from_sqlite_text(value).map(Some)
434 }
435
436 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
437 T::from_sqlite_real(value).map(Some)
438 }
439
440 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
441 T::from_sqlite_blob(value).map(Some)
442 }
443
444 fn from_sqlite_null() -> Result<Self, DrizzleError> {
445 Ok(None)
446 }
447}
448
449#[cfg(feature = "rusqlite")]
454impl DrizzleRowByIndex for rusqlite::Row<'_> {
455 fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
456 let value_ref = self.get_ref(idx)?;
457 match value_ref {
458 rusqlite::types::ValueRef::Integer(i) => T::from_sqlite_integer(i),
459 rusqlite::types::ValueRef::Text(s) => {
460 let s = std::str::from_utf8(s).map_err(|e| {
461 DrizzleError::ConversionError(format!("invalid UTF-8: {}", e).into())
462 })?;
463 T::from_sqlite_text(s)
464 }
465 rusqlite::types::ValueRef::Real(r) => T::from_sqlite_real(r),
466 rusqlite::types::ValueRef::Blob(b) => T::from_sqlite_blob(b),
467 rusqlite::types::ValueRef::Null => T::from_sqlite_null(),
468 }
469 }
470}
471
472#[cfg(feature = "rusqlite")]
473impl DrizzleRowByName for rusqlite::Row<'_> {
474 fn get_column_by_name<T: FromSQLiteValue>(&self, name: &str) -> Result<T, DrizzleError> {
475 let idx = self.as_ref().column_index(name)?;
476 DrizzleRowByIndex::get_column(self, idx)
477 }
478}
479
480#[cfg(feature = "libsql")]
481impl DrizzleRowByIndex for libsql::Row {
482 fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
483 let value = self.get_value(idx as i32)?;
484 match value {
485 libsql::Value::Integer(i) => T::from_sqlite_integer(i),
486 libsql::Value::Text(ref s) => T::from_sqlite_text(s),
487 libsql::Value::Real(r) => T::from_sqlite_real(r),
488 libsql::Value::Blob(ref b) => T::from_sqlite_blob(b),
489 libsql::Value::Null => T::from_sqlite_null(),
490 }
491 }
492}
493
494#[cfg(feature = "turso")]
495impl DrizzleRowByIndex for turso::Row {
496 fn get_column<T: FromSQLiteValue>(&self, idx: usize) -> Result<T, DrizzleError> {
497 let value = self.get_value(idx)?;
498 if value.is_null() {
499 T::from_sqlite_null()
500 } else if let Some(&i) = value.as_integer() {
501 T::from_sqlite_integer(i)
502 } else if let Some(s) = value.as_text() {
503 T::from_sqlite_text(s)
504 } else if let Some(&r) = value.as_real() {
505 T::from_sqlite_real(r)
506 } else if let Some(b) = value.as_blob() {
507 T::from_sqlite_blob(b)
508 } else {
509 Err(DrizzleError::ConversionError(
510 "unknown SQLite value type".into(),
511 ))
512 }
513 }
514}
515
516#[cfg(feature = "uuid")]
521impl FromSQLiteValue for uuid::Uuid {
522 fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
523 Err(DrizzleError::ConversionError(
524 "cannot convert INTEGER to UUID".into(),
525 ))
526 }
527
528 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
529 uuid::Uuid::parse_str(value).map_err(|e| {
530 DrizzleError::ConversionError(format!("invalid UUID string '{}': {}", value, e).into())
531 })
532 }
533
534 fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
535 Err(DrizzleError::ConversionError(
536 "cannot convert REAL to UUID".into(),
537 ))
538 }
539
540 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
541 uuid::Uuid::from_slice(value)
542 .map_err(|e| DrizzleError::ConversionError(format!("invalid UUID bytes: {}", e).into()))
543 }
544}
545
546#[cfg(feature = "arrayvec")]
547impl<const N: usize> FromSQLiteValue for arrayvec::ArrayString<N> {
548 fn from_sqlite_integer(value: i64) -> Result<Self, DrizzleError> {
549 let s = value.to_string();
550 arrayvec::ArrayString::from(&s).map_err(|_| {
551 DrizzleError::ConversionError(
552 format!(
553 "String length {} exceeds ArrayString capacity {}",
554 s.len(),
555 N
556 )
557 .into(),
558 )
559 })
560 }
561
562 fn from_sqlite_text(value: &str) -> Result<Self, DrizzleError> {
563 arrayvec::ArrayString::from(value).map_err(|_| {
564 DrizzleError::ConversionError(
565 format!(
566 "Text length {} exceeds ArrayString capacity {}",
567 value.len(),
568 N
569 )
570 .into(),
571 )
572 })
573 }
574
575 fn from_sqlite_real(value: f64) -> Result<Self, DrizzleError> {
576 let s = value.to_string();
577 arrayvec::ArrayString::from(&s).map_err(|_| {
578 DrizzleError::ConversionError(
579 format!(
580 "String length {} exceeds ArrayString capacity {}",
581 s.len(),
582 N
583 )
584 .into(),
585 )
586 })
587 }
588
589 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
590 let s = String::from_utf8(value.to_vec())
591 .map_err(|e| DrizzleError::ConversionError(format!("invalid UTF-8: {}", e).into()))?;
592 arrayvec::ArrayString::from(&s).map_err(|_| {
593 DrizzleError::ConversionError(
594 format!(
595 "String length {} exceeds ArrayString capacity {}",
596 s.len(),
597 N
598 )
599 .into(),
600 )
601 })
602 }
603}
604
605#[cfg(feature = "arrayvec")]
606impl<const N: usize> FromSQLiteValue for arrayvec::ArrayVec<u8, N> {
607 fn from_sqlite_integer(_value: i64) -> Result<Self, DrizzleError> {
608 Err(DrizzleError::ConversionError(
609 "cannot convert INTEGER to ArrayVec<u8>, use BLOB".into(),
610 ))
611 }
612
613 fn from_sqlite_text(_value: &str) -> Result<Self, DrizzleError> {
614 Err(DrizzleError::ConversionError(
615 "cannot convert TEXT to ArrayVec<u8>, use BLOB".into(),
616 ))
617 }
618
619 fn from_sqlite_real(_value: f64) -> Result<Self, DrizzleError> {
620 Err(DrizzleError::ConversionError(
621 "cannot convert REAL to ArrayVec<u8>, use BLOB".into(),
622 ))
623 }
624
625 fn from_sqlite_blob(value: &[u8]) -> Result<Self, DrizzleError> {
626 arrayvec::ArrayVec::try_from(value).map_err(|_| {
627 DrizzleError::ConversionError(
628 format!(
629 "Blob length {} exceeds ArrayVec capacity {}",
630 value.len(),
631 N
632 )
633 .into(),
634 )
635 })
636 }
637}