Skip to main content

drizzle_sqlite/values/
conversions.rs

1//! From and `TryFrom` implementations for `SQLiteValue`
2
3use super::{OwnedSQLiteValue, SQLiteValue};
4use crate::prelude::*;
5use drizzle_core::{error::DrizzleError, sql::SQL, traits::ToSQL};
6
7#[cfg(feature = "uuid")]
8use uuid::Uuid;
9
10//------------------------------------------------------------------------------
11// ToSQL Implementation
12//------------------------------------------------------------------------------
13
14impl<'a> ToSQL<'a, Self> for SQLiteValue<'a> {
15    fn to_sql(&self) -> SQL<'a, Self> {
16        SQL::param(self.clone())
17    }
18}
19
20//------------------------------------------------------------------------------
21// From OwnedSQLiteValue
22//------------------------------------------------------------------------------
23
24impl From<OwnedSQLiteValue> for SQLiteValue<'_> {
25    fn from(value: OwnedSQLiteValue) -> Self {
26        match value {
27            OwnedSQLiteValue::Integer(f) => SQLiteValue::Integer(f),
28            OwnedSQLiteValue::Real(r) => SQLiteValue::Real(r),
29            OwnedSQLiteValue::Text(v) => SQLiteValue::Text(Cow::Owned(v)),
30            OwnedSQLiteValue::Blob(v) => SQLiteValue::Blob(Cow::Owned(v.into())),
31            OwnedSQLiteValue::Null => SQLiteValue::Null,
32        }
33    }
34}
35
36impl<'a> From<&'a OwnedSQLiteValue> for SQLiteValue<'a> {
37    fn from(value: &'a OwnedSQLiteValue) -> Self {
38        match value {
39            OwnedSQLiteValue::Integer(f) => SQLiteValue::Integer(*f),
40            OwnedSQLiteValue::Real(r) => SQLiteValue::Real(*r),
41            OwnedSQLiteValue::Text(v) => SQLiteValue::Text(Cow::Borrowed(v)),
42            OwnedSQLiteValue::Blob(v) => SQLiteValue::Blob(Cow::Borrowed(v)),
43            OwnedSQLiteValue::Null => SQLiteValue::Null,
44        }
45    }
46}
47
48impl<'a> From<&'a Self> for SQLiteValue<'a> {
49    fn from(value: &'a Self) -> Self {
50        match value {
51            SQLiteValue::Integer(f) => SQLiteValue::Integer(*f),
52            SQLiteValue::Real(r) => SQLiteValue::Real(*r),
53            SQLiteValue::Text(v) => SQLiteValue::Text(Cow::Borrowed(v)),
54            SQLiteValue::Blob(v) => SQLiteValue::Blob(Cow::Borrowed(v)),
55            SQLiteValue::Null => SQLiteValue::Null,
56        }
57    }
58}
59
60impl<'a> From<Cow<'a, Self>> for SQLiteValue<'a> {
61    fn from(value: Cow<'a, Self>) -> Self {
62        match value {
63            Cow::Borrowed(r) => r.into(),
64            Cow::Owned(o) => o,
65        }
66    }
67}
68
69impl<'a> From<&'a Cow<'a, Self>> for SQLiteValue<'a> {
70    fn from(value: &'a Cow<'a, Self>) -> Self {
71        match value {
72            Cow::Borrowed(r) => (*r).into(),
73            Cow::Owned(o) => o.into(),
74        }
75    }
76}
77
78//------------------------------------------------------------------------------
79// From<T> implementations
80// Macro-based to reduce boilerplate
81//------------------------------------------------------------------------------
82
83/// Integer widths where `i64::from(T)` is infallible.
84macro_rules! impl_from_lossless_int_for_sqlite_value {
85    ($($ty:ty),* $(,)?) => {
86        $(
87            impl<'a> From<$ty> for SQLiteValue<'a> {
88                #[inline]
89                fn from(value: $ty) -> Self {
90                    SQLiteValue::Integer(i64::from(value))
91                }
92            }
93
94            impl<'a> From<&$ty> for SQLiteValue<'a> {
95                #[inline]
96                fn from(value: &$ty) -> Self {
97                    SQLiteValue::Integer(i64::from(*value))
98                }
99            }
100        )*
101    };
102}
103
104// Types that widen to i64 without loss.
105impl_from_lossless_int_for_sqlite_value!(i8, i16, i32, u8, u16, u32, bool);
106
107// i64 identity — no conversion needed.
108impl From<i64> for SQLiteValue<'_> {
109    #[inline]
110    fn from(value: i64) -> Self {
111        SQLiteValue::Integer(value)
112    }
113}
114
115impl From<&i64> for SQLiteValue<'_> {
116    #[inline]
117    fn from(value: &i64) -> Self {
118        SQLiteValue::Integer(*value)
119    }
120}
121
122// u64 → i64 by reinterpreting bits. SQLite stores INTEGER as signed 64-bit;
123// this matches the round-trip convention used by the matching `i64 → u64`
124// reinterpretation on read.
125impl From<u64> for SQLiteValue<'_> {
126    #[inline]
127    fn from(value: u64) -> Self {
128        SQLiteValue::Integer(value.cast_signed())
129    }
130}
131
132impl From<&u64> for SQLiteValue<'_> {
133    #[inline]
134    fn from(value: &u64) -> Self {
135        SQLiteValue::Integer(value.cast_signed())
136    }
137}
138
139// isize → i64. All Rust-supported targets have pointers ≤ 64 bits, so
140// `i64::try_from` succeeds; the saturating fallback is defensive only.
141impl From<isize> for SQLiteValue<'_> {
142    #[inline]
143    fn from(value: isize) -> Self {
144        SQLiteValue::Integer(i64::try_from(value).unwrap_or(i64::MAX))
145    }
146}
147
148impl From<&isize> for SQLiteValue<'_> {
149    #[inline]
150    fn from(value: &isize) -> Self {
151        SQLiteValue::from(*value)
152    }
153}
154
155// usize stores like u64 (bits reinterpreted), so values above `i64::MAX`
156// round-trip instead of saturating. `u64::try_from` succeeds on every
157// supported target.
158impl From<usize> for SQLiteValue<'_> {
159    #[inline]
160    fn from(value: usize) -> Self {
161        SQLiteValue::from(u64::try_from(value).unwrap_or(u64::MAX))
162    }
163}
164
165impl From<&usize> for SQLiteValue<'_> {
166    #[inline]
167    fn from(value: &usize) -> Self {
168        SQLiteValue::from(*value)
169    }
170}
171
172// f32 widens exactly into f64.
173impl From<f32> for SQLiteValue<'_> {
174    #[inline]
175    fn from(value: f32) -> Self {
176        SQLiteValue::Real(f64::from(value))
177    }
178}
179
180impl From<&f32> for SQLiteValue<'_> {
181    #[inline]
182    fn from(value: &f32) -> Self {
183        SQLiteValue::Real(f64::from(*value))
184    }
185}
186
187// f64 identity.
188impl From<f64> for SQLiteValue<'_> {
189    #[inline]
190    fn from(value: f64) -> Self {
191        SQLiteValue::Real(value)
192    }
193}
194
195impl From<&f64> for SQLiteValue<'_> {
196    #[inline]
197    fn from(value: &f64) -> Self {
198        SQLiteValue::Real(*value)
199    }
200}
201
202// --- String Types ---
203
204impl<'a> From<&'a str> for SQLiteValue<'a> {
205    fn from(value: &'a str) -> Self {
206        SQLiteValue::Text(Cow::Borrowed(value))
207    }
208}
209
210impl<'a> From<Cow<'a, str>> for SQLiteValue<'a> {
211    fn from(value: Cow<'a, str>) -> Self {
212        SQLiteValue::Text(value)
213    }
214}
215
216impl From<String> for SQLiteValue<'_> {
217    fn from(value: String) -> Self {
218        SQLiteValue::Text(Cow::Owned(value))
219    }
220}
221
222impl<'a> From<&'a String> for SQLiteValue<'a> {
223    fn from(value: &'a String) -> Self {
224        SQLiteValue::Text(Cow::Borrowed(value))
225    }
226}
227
228impl From<Box<String>> for SQLiteValue<'_> {
229    fn from(value: Box<String>) -> Self {
230        SQLiteValue::Text(Cow::Owned(*value))
231    }
232}
233
234impl<'a> From<&'a Box<String>> for SQLiteValue<'a> {
235    fn from(value: &'a Box<String>) -> Self {
236        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
237    }
238}
239
240impl From<Rc<String>> for SQLiteValue<'_> {
241    fn from(value: Rc<String>) -> Self {
242        SQLiteValue::Text(Cow::Owned(value.as_ref().clone()))
243    }
244}
245
246impl<'a> From<&'a Rc<String>> for SQLiteValue<'a> {
247    fn from(value: &'a Rc<String>) -> Self {
248        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
249    }
250}
251
252impl From<Arc<String>> for SQLiteValue<'_> {
253    fn from(value: Arc<String>) -> Self {
254        SQLiteValue::Text(Cow::Owned(value.as_ref().clone()))
255    }
256}
257
258impl<'a> From<&'a Arc<String>> for SQLiteValue<'a> {
259    fn from(value: &'a Arc<String>) -> Self {
260        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
261    }
262}
263
264impl From<Box<str>> for SQLiteValue<'_> {
265    fn from(value: Box<str>) -> Self {
266        SQLiteValue::Text(Cow::Owned(value.into()))
267    }
268}
269
270impl<'a> From<&'a Box<str>> for SQLiteValue<'a> {
271    fn from(value: &'a Box<str>) -> Self {
272        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
273    }
274}
275
276impl From<Rc<str>> for SQLiteValue<'_> {
277    fn from(value: Rc<str>) -> Self {
278        SQLiteValue::Text(Cow::Owned(value.as_ref().to_string()))
279    }
280}
281
282impl<'a> From<&'a Rc<str>> for SQLiteValue<'a> {
283    fn from(value: &'a Rc<str>) -> Self {
284        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
285    }
286}
287
288impl From<Arc<str>> for SQLiteValue<'_> {
289    fn from(value: Arc<str>) -> Self {
290        SQLiteValue::Text(Cow::Owned(value.as_ref().to_string()))
291    }
292}
293
294impl<'a> From<&'a Arc<str>> for SQLiteValue<'a> {
295    fn from(value: &'a Arc<str>) -> Self {
296        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
297    }
298}
299
300// --- ArrayString ---
301
302#[cfg(feature = "arrayvec")]
303impl<const N: usize> From<arrayvec::ArrayString<N>> for SQLiteValue<'_> {
304    fn from(value: arrayvec::ArrayString<N>) -> Self {
305        SQLiteValue::Text(Cow::Owned(value.to_string()))
306    }
307}
308
309#[cfg(feature = "arrayvec")]
310impl<const N: usize> From<&arrayvec::ArrayString<N>> for SQLiteValue<'_> {
311    fn from(value: &arrayvec::ArrayString<N>) -> Self {
312        SQLiteValue::Text(Cow::Owned(String::from(value.as_str())))
313    }
314}
315
316impl From<compact_str::CompactString> for SQLiteValue<'_> {
317    fn from(value: compact_str::CompactString) -> Self {
318        SQLiteValue::Text(Cow::Owned(value.to_string()))
319    }
320}
321
322impl<'a> From<&'a compact_str::CompactString> for SQLiteValue<'a> {
323    fn from(value: &'a compact_str::CompactString) -> Self {
324        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
325    }
326}
327
328// --- Binary Data ---
329
330impl<'a> From<&'a [u8]> for SQLiteValue<'a> {
331    fn from(value: &'a [u8]) -> Self {
332        SQLiteValue::Blob(Cow::Borrowed(value))
333    }
334}
335
336impl<'a> From<Cow<'a, [u8]>> for SQLiteValue<'a> {
337    fn from(value: Cow<'a, [u8]>) -> Self {
338        SQLiteValue::Blob(value)
339    }
340}
341
342impl From<Vec<u8>> for SQLiteValue<'_> {
343    fn from(value: Vec<u8>) -> Self {
344        SQLiteValue::Blob(Cow::Owned(value))
345    }
346}
347
348impl From<Box<Vec<u8>>> for SQLiteValue<'_> {
349    fn from(value: Box<Vec<u8>>) -> Self {
350        SQLiteValue::Blob(Cow::Owned(*value))
351    }
352}
353
354impl<'a> From<&'a Box<Vec<u8>>> for SQLiteValue<'a> {
355    fn from(value: &'a Box<Vec<u8>>) -> Self {
356        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
357    }
358}
359
360impl From<Rc<Vec<u8>>> for SQLiteValue<'_> {
361    fn from(value: Rc<Vec<u8>>) -> Self {
362        SQLiteValue::Blob(Cow::Owned(value.as_ref().clone()))
363    }
364}
365
366impl<'a> From<&'a Rc<Vec<u8>>> for SQLiteValue<'a> {
367    fn from(value: &'a Rc<Vec<u8>>) -> Self {
368        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
369    }
370}
371
372impl From<Arc<Vec<u8>>> for SQLiteValue<'_> {
373    fn from(value: Arc<Vec<u8>>) -> Self {
374        SQLiteValue::Blob(Cow::Owned(value.as_ref().clone()))
375    }
376}
377
378impl<'a> From<&'a Arc<Vec<u8>>> for SQLiteValue<'a> {
379    fn from(value: &'a Arc<Vec<u8>>) -> Self {
380        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
381    }
382}
383
384// --- ArrayVec<u8, N> ---
385
386#[cfg(feature = "arrayvec")]
387impl<const N: usize> From<arrayvec::ArrayVec<u8, N>> for SQLiteValue<'_> {
388    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
389        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
390    }
391}
392
393#[cfg(feature = "arrayvec")]
394impl<const N: usize> From<&arrayvec::ArrayVec<u8, N>> for SQLiteValue<'_> {
395    fn from(value: &arrayvec::ArrayVec<u8, N>) -> Self {
396        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
397    }
398}
399
400#[cfg(feature = "bytes")]
401impl From<bytes::Bytes> for SQLiteValue<'_> {
402    fn from(value: bytes::Bytes) -> Self {
403        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
404    }
405}
406
407#[cfg(feature = "bytes")]
408impl<'a> From<&'a bytes::Bytes> for SQLiteValue<'a> {
409    fn from(value: &'a bytes::Bytes) -> Self {
410        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
411    }
412}
413
414#[cfg(feature = "bytes")]
415impl From<bytes::BytesMut> for SQLiteValue<'_> {
416    fn from(value: bytes::BytesMut) -> Self {
417        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
418    }
419}
420
421#[cfg(feature = "bytes")]
422impl<'a> From<&'a bytes::BytesMut> for SQLiteValue<'a> {
423    fn from(value: &'a bytes::BytesMut) -> Self {
424        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
425    }
426}
427
428#[cfg(feature = "smallvec")]
429impl<const N: usize> From<smallvec::SmallVec<[u8; N]>> for SQLiteValue<'_> {
430    fn from(value: smallvec::SmallVec<[u8; N]>) -> Self {
431        SQLiteValue::Blob(Cow::Owned(value.into_vec()))
432    }
433}
434
435#[cfg(feature = "smallvec")]
436impl<const N: usize> From<&smallvec::SmallVec<[u8; N]>> for SQLiteValue<'_> {
437    fn from(value: &smallvec::SmallVec<[u8; N]>) -> Self {
438        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
439    }
440}
441
442// --- Chrono Date/Time Types (stored as ISO-8601 text) ---
443
444#[cfg(feature = "chrono")]
445impl From<chrono::NaiveDate> for SQLiteValue<'_> {
446    fn from(value: chrono::NaiveDate) -> Self {
447        SQLiteValue::Text(Cow::Owned(value.to_string()))
448    }
449}
450
451#[cfg(feature = "chrono")]
452impl From<&chrono::NaiveDate> for SQLiteValue<'_> {
453    fn from(value: &chrono::NaiveDate) -> Self {
454        SQLiteValue::Text(Cow::Owned(value.to_string()))
455    }
456}
457
458#[cfg(feature = "chrono")]
459impl From<chrono::NaiveTime> for SQLiteValue<'_> {
460    fn from(value: chrono::NaiveTime) -> Self {
461        SQLiteValue::Text(Cow::Owned(value.to_string()))
462    }
463}
464
465#[cfg(feature = "chrono")]
466impl From<&chrono::NaiveTime> for SQLiteValue<'_> {
467    fn from(value: &chrono::NaiveTime) -> Self {
468        SQLiteValue::Text(Cow::Owned(value.to_string()))
469    }
470}
471
472#[cfg(feature = "chrono")]
473impl From<chrono::NaiveDateTime> for SQLiteValue<'_> {
474    fn from(value: chrono::NaiveDateTime) -> Self {
475        SQLiteValue::Text(Cow::Owned(value.to_string()))
476    }
477}
478
479#[cfg(feature = "chrono")]
480impl From<&chrono::NaiveDateTime> for SQLiteValue<'_> {
481    fn from(value: &chrono::NaiveDateTime) -> Self {
482        SQLiteValue::Text(Cow::Owned(value.to_string()))
483    }
484}
485
486#[cfg(feature = "chrono")]
487impl From<chrono::DateTime<chrono::FixedOffset>> for SQLiteValue<'_> {
488    fn from(value: chrono::DateTime<chrono::FixedOffset>) -> Self {
489        SQLiteValue::Text(Cow::Owned(value.to_rfc3339()))
490    }
491}
492
493#[cfg(feature = "chrono")]
494impl From<&chrono::DateTime<chrono::FixedOffset>> for SQLiteValue<'_> {
495    fn from(value: &chrono::DateTime<chrono::FixedOffset>) -> Self {
496        SQLiteValue::Text(Cow::Owned(value.to_rfc3339()))
497    }
498}
499
500#[cfg(feature = "chrono")]
501impl From<chrono::DateTime<chrono::Utc>> for SQLiteValue<'_> {
502    fn from(value: chrono::DateTime<chrono::Utc>) -> Self {
503        SQLiteValue::Text(Cow::Owned(value.to_rfc3339()))
504    }
505}
506
507#[cfg(feature = "chrono")]
508impl From<&chrono::DateTime<chrono::Utc>> for SQLiteValue<'_> {
509    fn from(value: &chrono::DateTime<chrono::Utc>) -> Self {
510        SQLiteValue::Text(Cow::Owned(value.to_rfc3339()))
511    }
512}
513
514#[cfg(feature = "chrono")]
515impl From<chrono::Duration> for SQLiteValue<'_> {
516    fn from(value: chrono::Duration) -> Self {
517        SQLiteValue::from(&value)
518    }
519}
520
521#[cfg(feature = "chrono")]
522impl From<&chrono::Duration> for SQLiteValue<'_> {
523    fn from(value: &chrono::Duration) -> Self {
524        let abs = value.abs();
525        SQLiteValue::Text(Cow::Owned(super::duration::format(
526            *value < chrono::Duration::zero(),
527            abs.num_seconds().unsigned_abs(),
528            abs.subsec_nanos().unsigned_abs(),
529        )))
530    }
531}
532
533// --- Time crate Date/Time Types (stored as ISO-8601 text) ---
534
535#[cfg(feature = "time")]
536impl From<time::Date> for SQLiteValue<'_> {
537    fn from(value: time::Date) -> Self {
538        SQLiteValue::Text(Cow::Owned(
539            value
540                .format(&time::format_description::well_known::Iso8601::DATE)
541                .unwrap_or_else(|_| value.to_string()),
542        ))
543    }
544}
545
546#[cfg(feature = "time")]
547impl From<&time::Date> for SQLiteValue<'_> {
548    fn from(value: &time::Date) -> Self {
549        SQLiteValue::Text(Cow::Owned(
550            value
551                .format(&time::format_description::well_known::Iso8601::DATE)
552                .unwrap_or_else(|_| value.to_string()),
553        ))
554    }
555}
556
557/// `HH:MM:SS.fraction`, as SQLite's time functions read it. (ISO 8601's
558/// time-only format starts with a `T`, which they reject.)
559#[cfg(feature = "time")]
560impl From<time::Time> for SQLiteValue<'_> {
561    fn from(value: time::Time) -> Self {
562        SQLiteValue::Text(Cow::Owned(
563            value
564                .format(time::macros::format_description!(
565                    "[hour]:[minute]:[second].[subsecond]"
566                ))
567                .unwrap_or_else(|_| value.to_string()),
568        ))
569    }
570}
571
572#[cfg(feature = "time")]
573impl From<&time::Time> for SQLiteValue<'_> {
574    fn from(value: &time::Time) -> Self {
575        Self::from(*value)
576    }
577}
578
579#[cfg(feature = "time")]
580impl From<time::PrimitiveDateTime> for SQLiteValue<'_> {
581    fn from(value: time::PrimitiveDateTime) -> Self {
582        SQLiteValue::Text(Cow::Owned(
583            value
584                .format(&time::format_description::well_known::Iso8601::DATE_TIME)
585                .unwrap_or_else(|_| value.to_string()),
586        ))
587    }
588}
589
590#[cfg(feature = "time")]
591impl From<&time::PrimitiveDateTime> for SQLiteValue<'_> {
592    fn from(value: &time::PrimitiveDateTime) -> Self {
593        SQLiteValue::Text(Cow::Owned(
594            value
595                .format(&time::format_description::well_known::Iso8601::DATE_TIME)
596                .unwrap_or_else(|_| value.to_string()),
597        ))
598    }
599}
600
601#[cfg(feature = "time")]
602impl From<time::OffsetDateTime> for SQLiteValue<'_> {
603    fn from(value: time::OffsetDateTime) -> Self {
604        SQLiteValue::Text(Cow::Owned(
605            value
606                .format(&time::format_description::well_known::Rfc3339)
607                .unwrap_or_else(|_| value.to_string()),
608        ))
609    }
610}
611
612#[cfg(feature = "time")]
613impl From<&time::OffsetDateTime> for SQLiteValue<'_> {
614    fn from(value: &time::OffsetDateTime) -> Self {
615        SQLiteValue::Text(Cow::Owned(
616            value
617                .format(&time::format_description::well_known::Rfc3339)
618                .unwrap_or_else(|_| value.to_string()),
619        ))
620    }
621}
622
623#[cfg(feature = "time")]
624impl From<time::Duration> for SQLiteValue<'_> {
625    fn from(value: time::Duration) -> Self {
626        SQLiteValue::from(&value)
627    }
628}
629
630#[cfg(feature = "time")]
631impl From<&time::Duration> for SQLiteValue<'_> {
632    fn from(value: &time::Duration) -> Self {
633        SQLiteValue::Text(Cow::Owned(super::duration::format(
634            value.is_negative(),
635            value.whole_seconds().unsigned_abs(),
636            value.subsec_nanoseconds().unsigned_abs(),
637        )))
638    }
639}
640
641// --- jiff ---
642//
643// ISO 8601 text, as SQLite's date and time functions read it. A civil
644// datetime puts a space between date and time, as `datetime()` and
645// `CURRENT_TIMESTAMP` do; a timestamp is RFC 3339 in UTC.
646
647#[cfg(feature = "jiff")]
648impl From<jiff::civil::Date> for SQLiteValue<'_> {
649    fn from(value: jiff::civil::Date) -> Self {
650        SQLiteValue::Text(Cow::Owned(value.to_string()))
651    }
652}
653
654#[cfg(feature = "jiff")]
655impl From<&jiff::civil::Date> for SQLiteValue<'_> {
656    fn from(value: &jiff::civil::Date) -> Self {
657        Self::from(*value)
658    }
659}
660
661#[cfg(feature = "jiff")]
662impl From<jiff::civil::Time> for SQLiteValue<'_> {
663    fn from(value: jiff::civil::Time) -> Self {
664        SQLiteValue::Text(Cow::Owned(value.to_string()))
665    }
666}
667
668#[cfg(feature = "jiff")]
669impl From<&jiff::civil::Time> for SQLiteValue<'_> {
670    fn from(value: &jiff::civil::Time) -> Self {
671        Self::from(*value)
672    }
673}
674
675#[cfg(feature = "jiff")]
676impl From<jiff::civil::DateTime> for SQLiteValue<'_> {
677    fn from(value: jiff::civil::DateTime) -> Self {
678        SQLiteValue::Text(Cow::Owned(format!("{} {}", value.date(), value.time())))
679    }
680}
681
682#[cfg(feature = "jiff")]
683impl From<&jiff::civil::DateTime> for SQLiteValue<'_> {
684    fn from(value: &jiff::civil::DateTime) -> Self {
685        Self::from(*value)
686    }
687}
688
689#[cfg(feature = "jiff")]
690impl From<jiff::Timestamp> for SQLiteValue<'_> {
691    fn from(value: jiff::Timestamp) -> Self {
692        SQLiteValue::Text(Cow::Owned(value.to_string()))
693    }
694}
695
696#[cfg(feature = "jiff")]
697impl From<&jiff::Timestamp> for SQLiteValue<'_> {
698    fn from(value: &jiff::Timestamp) -> Self {
699        Self::from(*value)
700    }
701}
702
703// --- Decimal (stored as text for lossless round-trip) ---
704
705#[cfg(feature = "rust-decimal")]
706impl From<rust_decimal::Decimal> for SQLiteValue<'_> {
707    fn from(value: rust_decimal::Decimal) -> Self {
708        SQLiteValue::Text(Cow::Owned(value.to_string()))
709    }
710}
711
712#[cfg(feature = "rust-decimal")]
713impl From<&rust_decimal::Decimal> for SQLiteValue<'_> {
714    fn from(value: &rust_decimal::Decimal) -> Self {
715        SQLiteValue::Text(Cow::Owned(value.to_string()))
716    }
717}
718
719// --- JSON ---
720
721#[cfg(feature = "serde")]
722impl From<serde_json::Value> for SQLiteValue<'_> {
723    fn from(value: serde_json::Value) -> Self {
724        SQLiteValue::Text(Cow::Owned(value.to_string()))
725    }
726}
727
728#[cfg(feature = "serde")]
729impl From<&serde_json::Value> for SQLiteValue<'_> {
730    fn from(value: &serde_json::Value) -> Self {
731        SQLiteValue::Text(Cow::Owned(value.to_string()))
732    }
733}
734
735// --- UUID ---
736
737#[cfg(feature = "uuid")]
738impl From<Uuid> for SQLiteValue<'_> {
739    fn from(value: Uuid) -> Self {
740        SQLiteValue::Blob(Cow::Owned(value.as_bytes().to_vec()))
741    }
742}
743
744#[cfg(feature = "uuid")]
745impl<'a> From<&'a Uuid> for SQLiteValue<'a> {
746    fn from(value: &'a Uuid) -> Self {
747        SQLiteValue::Blob(Cow::Borrowed(value.as_bytes()))
748    }
749}
750
751// --- Option Types ---
752/// `None` is NULL.
753///
754/// # Panics
755///
756/// Panics when `T`'s conversion fails (for example a JSON payload whose
757/// `Serialize` implementation errors), rather than storing NULL in place of
758/// the value.
759impl<T> From<Option<T>> for SQLiteValue<'_>
760where
761    T: TryInto<Self>,
762{
763    fn from(value: Option<T>) -> Self {
764        value.map_or(SQLiteValue::Null, |v| {
765            v.try_into().unwrap_or_else(|_| {
766                panic!(
767                    "could not convert a `{}` to a SQLite value",
768                    core::any::type_name::<T>()
769                )
770            })
771        })
772    }
773}
774
775// --- Cow integration for SQL struct ---
776impl<'a> From<SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
777    fn from(value: SQLiteValue<'a>) -> Self {
778        Cow::Owned(value)
779    }
780}
781
782impl<'a> From<&'a SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
783    fn from(value: &'a SQLiteValue<'a>) -> Self {
784        Cow::Borrowed(value)
785    }
786}
787
788//------------------------------------------------------------------------------
789// TryFrom<SQLiteValue> implementations
790// Uses the FromSQLiteValue trait via convert() for unified conversion logic
791//------------------------------------------------------------------------------
792
793/// Macro to implement `TryFrom`<SQLiteValue> for types implementing `FromSQLiteValue`
794macro_rules! impl_try_from_sqlite_value {
795    ($($ty:ty),* $(,)?) => {
796        $(
797            impl<'a> TryFrom<SQLiteValue<'a>> for $ty {
798                type Error = DrizzleError;
799
800                #[inline]
801                fn try_from(value: SQLiteValue<'a>) -> Result<Self, Self::Error> {
802                    value.convert()
803                }
804            }
805        )*
806    };
807}
808
809impl_try_from_sqlite_value!(
810    i8,
811    i16,
812    i32,
813    i64,
814    isize,
815    u8,
816    u16,
817    u32,
818    u64,
819    usize,
820    f32,
821    f64,
822    bool,
823    String,
824    Box<String>,
825    Rc<String>,
826    Arc<String>,
827    Box<str>,
828    Rc<str>,
829    Arc<str>,
830    Box<Vec<u8>>,
831    Rc<Vec<u8>>,
832    Arc<Vec<u8>>,
833    Vec<u8>,
834    compact_str::CompactString,
835);
836
837#[cfg(feature = "uuid")]
838impl_try_from_sqlite_value!(Uuid);
839
840#[cfg(feature = "chrono")]
841impl_try_from_sqlite_value!(
842    chrono::NaiveDate,
843    chrono::NaiveTime,
844    chrono::NaiveDateTime,
845    chrono::DateTime<chrono::FixedOffset>,
846    chrono::DateTime<chrono::Utc>,
847    chrono::Duration,
848);
849
850#[cfg(feature = "time")]
851impl_try_from_sqlite_value!(
852    time::Date,
853    time::Time,
854    time::PrimitiveDateTime,
855    time::OffsetDateTime,
856    time::Duration,
857);
858
859#[cfg(feature = "rust-decimal")]
860impl_try_from_sqlite_value!(rust_decimal::Decimal);
861
862#[cfg(feature = "serde")]
863impl_try_from_sqlite_value!(serde_json::Value);
864
865#[cfg(feature = "bytes")]
866impl_try_from_sqlite_value!(bytes::Bytes, bytes::BytesMut);
867
868#[cfg(feature = "smallvec")]
869impl<const N: usize> TryFrom<SQLiteValue<'_>> for smallvec::SmallVec<[u8; N]> {
870    type Error = DrizzleError;
871
872    fn try_from(value: SQLiteValue<'_>) -> Result<Self, Self::Error> {
873        value.convert()
874    }
875}
876
877//------------------------------------------------------------------------------
878// TryFrom<&SQLiteValue> implementations for borrowing without consuming
879// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
880//------------------------------------------------------------------------------
881
882/// Macro to implement `TryFrom`<&`SQLiteValue`> for types implementing `FromSQLiteValue`
883macro_rules! impl_try_from_sqlite_value_ref {
884    ($($ty:ty),* $(,)?) => {
885        $(
886            impl<'a> TryFrom<&SQLiteValue<'a>> for $ty {
887                type Error = DrizzleError;
888
889                #[inline]
890                fn try_from(value: &SQLiteValue<'a>) -> Result<Self, Self::Error> {
891                    value.convert_ref()
892                }
893            }
894        )*
895    };
896}
897
898impl_try_from_sqlite_value_ref!(
899    i8,
900    i16,
901    i32,
902    i64,
903    isize,
904    u8,
905    u16,
906    u32,
907    u64,
908    usize,
909    f32,
910    f64,
911    bool,
912    String,
913    Box<String>,
914    Rc<String>,
915    Arc<String>,
916    Box<str>,
917    Rc<str>,
918    Arc<str>,
919    Box<Vec<u8>>,
920    Rc<Vec<u8>>,
921    Arc<Vec<u8>>,
922    Vec<u8>,
923    compact_str::CompactString,
924);
925
926#[cfg(feature = "uuid")]
927impl_try_from_sqlite_value_ref!(Uuid);
928
929#[cfg(feature = "chrono")]
930impl_try_from_sqlite_value_ref!(
931    chrono::NaiveDate,
932    chrono::NaiveTime,
933    chrono::NaiveDateTime,
934    chrono::DateTime<chrono::FixedOffset>,
935    chrono::DateTime<chrono::Utc>,
936    chrono::Duration,
937);
938
939#[cfg(feature = "time")]
940impl_try_from_sqlite_value_ref!(
941    time::Date,
942    time::Time,
943    time::PrimitiveDateTime,
944    time::OffsetDateTime,
945    time::Duration,
946);
947
948#[cfg(feature = "rust-decimal")]
949impl_try_from_sqlite_value_ref!(rust_decimal::Decimal);
950
951#[cfg(feature = "serde")]
952impl_try_from_sqlite_value_ref!(serde_json::Value);
953
954#[cfg(feature = "bytes")]
955impl_try_from_sqlite_value_ref!(bytes::Bytes, bytes::BytesMut);
956
957#[cfg(feature = "smallvec")]
958impl<const N: usize> TryFrom<&SQLiteValue<'_>> for smallvec::SmallVec<[u8; N]> {
959    type Error = DrizzleError;
960
961    fn try_from(value: &SQLiteValue<'_>) -> Result<Self, Self::Error> {
962        value.convert_ref()
963    }
964}
965
966// --- Borrowed reference types (cannot use FromSQLiteValue) ---
967
968impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a str {
969    type Error = DrizzleError;
970
971    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
972        match value {
973            SQLiteValue::Text(cow) => Ok(cow.as_ref()),
974            _ => Err(DrizzleError::ConversionError(
975                format!("Cannot convert {value:?} to &str").into(),
976            )),
977        }
978    }
979}
980
981impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a [u8] {
982    type Error = DrizzleError;
983
984    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
985        match value {
986            SQLiteValue::Blob(cow) => Ok(cow.as_ref()),
987            _ => Err(DrizzleError::ConversionError(
988                format!("Cannot convert {value:?} to &[u8]").into(),
989            )),
990        }
991    }
992}
993
994#[cfg(test)]
995mod tests {
996    use super::SQLiteValue;
997    use crate::traits::FromSQLiteValue;
998
999    fn stored(value: SQLiteValue<'_>) -> i64 {
1000        match value {
1001            SQLiteValue::Integer(i) => i,
1002            other => panic!("expected INTEGER, got {other:?}"),
1003        }
1004    }
1005
1006    // `u64`/`usize` store their bits as a signed INTEGER; reading must undo
1007    // that, including for values above `i64::MAX`.
1008    #[test]
1009    fn unsigned_64_bit_values_round_trip_above_i64_max() {
1010        for value in [
1011            0,
1012            i64::MAX.cast_unsigned(),
1013            i64::MAX.cast_unsigned() + 1,
1014            u64::MAX,
1015        ] {
1016            assert_eq!(
1017                u64::from_sqlite_integer(stored(value.into())).unwrap(),
1018                value
1019            );
1020            let size = usize::try_from(value).unwrap();
1021            assert_eq!(
1022                usize::from_sqlite_integer(stored(size.into())).unwrap(),
1023                size
1024            );
1025        }
1026    }
1027}