Skip to main content

drizzle_sqlite/values/owned/
conversions.rs

1//! `From<T>` and `TryFrom<OwnedSQLiteValue>` implementations.
2
3use super::OwnedSQLiteValue;
4use crate::prelude::*;
5use drizzle_core::error::DrizzleError;
6
7#[cfg(feature = "uuid")]
8use uuid::Uuid;
9
10//------------------------------------------------------------------------------
11// From<T> implementations
12// Macro-based to reduce boilerplate
13//------------------------------------------------------------------------------
14
15/// Integer widths where `i64::from(T)` is infallible.
16macro_rules! impl_from_lossless_int_for_owned_sqlite_value {
17    ($($ty:ty),* $(,)?) => {
18        $(
19            impl From<$ty> for OwnedSQLiteValue {
20                #[inline]
21                fn from(value: $ty) -> Self {
22                    OwnedSQLiteValue::Integer(i64::from(value))
23                }
24            }
25
26            impl From<&$ty> for OwnedSQLiteValue {
27                #[inline]
28                fn from(value: &$ty) -> Self {
29                    OwnedSQLiteValue::Integer(i64::from(*value))
30                }
31            }
32        )*
33    };
34}
35
36impl_from_lossless_int_for_owned_sqlite_value!(i8, i16, i32, u8, u16, u32, bool);
37
38// i64 identity.
39impl From<i64> for OwnedSQLiteValue {
40    #[inline]
41    fn from(value: i64) -> Self {
42        Self::Integer(value)
43    }
44}
45
46impl From<&i64> for OwnedSQLiteValue {
47    #[inline]
48    fn from(value: &i64) -> Self {
49        Self::Integer(*value)
50    }
51}
52
53// u64 → i64 bit reinterpretation. SQLite INTEGER is signed 64-bit; this matches
54// the matching `i64 → u64` reinterpretation on read.
55impl From<u64> for OwnedSQLiteValue {
56    #[inline]
57    fn from(value: u64) -> Self {
58        Self::Integer(value.cast_signed())
59    }
60}
61
62impl From<&u64> for OwnedSQLiteValue {
63    #[inline]
64    fn from(value: &u64) -> Self {
65        Self::Integer(value.cast_signed())
66    }
67}
68
69/// Pointer-sized integer widths (usize/isize). All supported targets have
70/// pointers ≤ 64 bits; the saturating fallback is defensive only.
71macro_rules! impl_from_pointer_int_for_owned_sqlite_value {
72    ($($ty:ty),* $(,)?) => {
73        $(
74            impl From<$ty> for OwnedSQLiteValue {
75                #[inline]
76                fn from(value: $ty) -> Self {
77                    OwnedSQLiteValue::Integer(i64::try_from(value).unwrap_or(i64::MAX))
78                }
79            }
80
81            impl From<&$ty> for OwnedSQLiteValue {
82                #[inline]
83                fn from(value: &$ty) -> Self {
84                    OwnedSQLiteValue::Integer(i64::try_from(*value).unwrap_or(i64::MAX))
85                }
86            }
87        )*
88    };
89}
90
91impl_from_pointer_int_for_owned_sqlite_value!(isize, usize);
92
93// f32 widens exactly into f64.
94impl From<f32> for OwnedSQLiteValue {
95    #[inline]
96    fn from(value: f32) -> Self {
97        Self::Real(f64::from(value))
98    }
99}
100
101impl From<&f32> for OwnedSQLiteValue {
102    #[inline]
103    fn from(value: &f32) -> Self {
104        Self::Real(f64::from(*value))
105    }
106}
107
108// f64 identity.
109impl From<f64> for OwnedSQLiteValue {
110    #[inline]
111    fn from(value: f64) -> Self {
112        Self::Real(value)
113    }
114}
115
116impl From<&f64> for OwnedSQLiteValue {
117    #[inline]
118    fn from(value: &f64) -> Self {
119        Self::Real(*value)
120    }
121}
122
123// --- String Types ---
124
125impl From<&str> for OwnedSQLiteValue {
126    fn from(value: &str) -> Self {
127        Self::Text(value.to_string())
128    }
129}
130
131impl From<Cow<'_, str>> for OwnedSQLiteValue {
132    fn from(value: Cow<'_, str>) -> Self {
133        Self::Text(value.into_owned())
134    }
135}
136
137impl From<String> for OwnedSQLiteValue {
138    fn from(value: String) -> Self {
139        Self::Text(value)
140    }
141}
142
143impl From<&String> for OwnedSQLiteValue {
144    fn from(value: &String) -> Self {
145        Self::Text(value.clone())
146    }
147}
148
149impl From<Box<String>> for OwnedSQLiteValue {
150    fn from(value: Box<String>) -> Self {
151        Self::Text(*value)
152    }
153}
154
155impl From<&Box<String>> for OwnedSQLiteValue {
156    fn from(value: &Box<String>) -> Self {
157        Self::Text(value.as_ref().clone())
158    }
159}
160
161impl From<Rc<String>> for OwnedSQLiteValue {
162    fn from(value: Rc<String>) -> Self {
163        Self::Text(value.as_ref().clone())
164    }
165}
166
167impl From<&Rc<String>> for OwnedSQLiteValue {
168    fn from(value: &Rc<String>) -> Self {
169        Self::Text(value.as_ref().clone())
170    }
171}
172
173impl From<Arc<String>> for OwnedSQLiteValue {
174    fn from(value: Arc<String>) -> Self {
175        Self::Text(value.as_ref().clone())
176    }
177}
178
179impl From<&Arc<String>> for OwnedSQLiteValue {
180    fn from(value: &Arc<String>) -> Self {
181        Self::Text(value.as_ref().clone())
182    }
183}
184
185impl From<Box<str>> for OwnedSQLiteValue {
186    fn from(value: Box<str>) -> Self {
187        Self::Text(value.into())
188    }
189}
190
191impl From<&Box<str>> for OwnedSQLiteValue {
192    fn from(value: &Box<str>) -> Self {
193        Self::Text(value.as_ref().to_string())
194    }
195}
196
197impl From<Rc<str>> for OwnedSQLiteValue {
198    fn from(value: Rc<str>) -> Self {
199        Self::Text(value.as_ref().to_string())
200    }
201}
202
203impl From<&Rc<str>> for OwnedSQLiteValue {
204    fn from(value: &Rc<str>) -> Self {
205        Self::Text(value.as_ref().to_string())
206    }
207}
208
209impl From<Arc<str>> for OwnedSQLiteValue {
210    fn from(value: Arc<str>) -> Self {
211        Self::Text(value.as_ref().to_string())
212    }
213}
214
215impl From<&Arc<str>> for OwnedSQLiteValue {
216    fn from(value: &Arc<str>) -> Self {
217        Self::Text(value.as_ref().to_string())
218    }
219}
220
221// --- Binary Data ---
222
223impl From<&[u8]> for OwnedSQLiteValue {
224    fn from(value: &[u8]) -> Self {
225        Self::Blob(value.to_vec().into_boxed_slice())
226    }
227}
228
229impl From<Cow<'_, [u8]>> for OwnedSQLiteValue {
230    fn from(value: Cow<'_, [u8]>) -> Self {
231        Self::Blob(value.into_owned().into_boxed_slice())
232    }
233}
234
235impl From<Vec<u8>> for OwnedSQLiteValue {
236    fn from(value: Vec<u8>) -> Self {
237        Self::Blob(value.into_boxed_slice())
238    }
239}
240
241impl From<Box<Vec<u8>>> for OwnedSQLiteValue {
242    fn from(value: Box<Vec<u8>>) -> Self {
243        Self::Blob(value.into_boxed_slice())
244    }
245}
246
247impl From<&Box<Vec<u8>>> for OwnedSQLiteValue {
248    fn from(value: &Box<Vec<u8>>) -> Self {
249        Self::Blob(value.as_slice().to_vec().into_boxed_slice())
250    }
251}
252
253impl From<Rc<Vec<u8>>> for OwnedSQLiteValue {
254    fn from(value: Rc<Vec<u8>>) -> Self {
255        Self::Blob(value.as_slice().to_vec().into_boxed_slice())
256    }
257}
258
259impl From<&Rc<Vec<u8>>> for OwnedSQLiteValue {
260    fn from(value: &Rc<Vec<u8>>) -> Self {
261        Self::Blob(value.as_slice().to_vec().into_boxed_slice())
262    }
263}
264
265impl From<Arc<Vec<u8>>> for OwnedSQLiteValue {
266    fn from(value: Arc<Vec<u8>>) -> Self {
267        Self::Blob(value.as_slice().to_vec().into_boxed_slice())
268    }
269}
270
271impl From<&Arc<Vec<u8>>> for OwnedSQLiteValue {
272    fn from(value: &Arc<Vec<u8>>) -> Self {
273        Self::Blob(value.as_slice().to_vec().into_boxed_slice())
274    }
275}
276
277// --- UUID ---
278
279#[cfg(feature = "uuid")]
280impl From<Uuid> for OwnedSQLiteValue {
281    fn from(value: Uuid) -> Self {
282        Self::Blob(value.as_bytes().to_vec().into_boxed_slice())
283    }
284}
285
286#[cfg(feature = "uuid")]
287impl From<&Uuid> for OwnedSQLiteValue {
288    fn from(value: &Uuid) -> Self {
289        Self::Blob(value.as_bytes().to_vec().into_boxed_slice())
290    }
291}
292
293#[cfg(feature = "arrayvec")]
294impl<const N: usize> From<arrayvec::ArrayString<N>> for OwnedSQLiteValue {
295    fn from(value: arrayvec::ArrayString<N>) -> Self {
296        Self::Text(value.to_string())
297    }
298}
299
300impl From<compact_str::CompactString> for OwnedSQLiteValue {
301    fn from(value: compact_str::CompactString) -> Self {
302        Self::Text(value.to_string())
303    }
304}
305
306#[cfg(feature = "arrayvec")]
307impl<const N: usize> From<arrayvec::ArrayVec<u8, N>> for OwnedSQLiteValue {
308    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
309        Self::Blob(value.to_vec().into_boxed_slice())
310    }
311}
312
313#[cfg(feature = "bytes")]
314impl From<bytes::Bytes> for OwnedSQLiteValue {
315    fn from(value: bytes::Bytes) -> Self {
316        Self::Blob(value.to_vec().into_boxed_slice())
317    }
318}
319
320#[cfg(feature = "bytes")]
321impl From<bytes::BytesMut> for OwnedSQLiteValue {
322    fn from(value: bytes::BytesMut) -> Self {
323        Self::Blob(value.to_vec().into_boxed_slice())
324    }
325}
326
327#[cfg(feature = "smallvec")]
328impl<const N: usize> From<smallvec::SmallVec<[u8; N]>> for OwnedSQLiteValue {
329    fn from(value: smallvec::SmallVec<[u8; N]>) -> Self {
330        Self::Blob(value.into_vec().into_boxed_slice())
331    }
332}
333
334// --- Option Types ---
335/// `None` is NULL.
336///
337/// # Panics
338///
339/// Panics when `T`'s conversion fails, rather than storing NULL in place of
340/// the value.
341impl<T> From<Option<T>> for OwnedSQLiteValue
342where
343    T: TryInto<Self>,
344{
345    fn from(value: Option<T>) -> Self {
346        value.map_or(Self::Null, |v| {
347            v.try_into().unwrap_or_else(|_| {
348                panic!(
349                    "could not convert a `{}` to a SQLite value",
350                    core::any::type_name::<T>()
351                )
352            })
353        })
354    }
355}
356
357//------------------------------------------------------------------------------
358// TryFrom<OwnedSQLiteValue> implementations
359// Uses the FromSQLiteValue trait via convert() for unified conversion logic
360//------------------------------------------------------------------------------
361
362/// Macro to implement `TryFrom`<OwnedSQLiteValue> for types implementing `FromSQLiteValue`
363macro_rules! impl_try_from_owned_sqlite_value {
364    ($($ty:ty),* $(,)?) => {
365        $(
366            impl TryFrom<OwnedSQLiteValue> for $ty {
367                type Error = DrizzleError;
368
369                #[inline]
370                fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
371                    value.convert()
372                }
373            }
374        )*
375    };
376}
377
378impl_try_from_owned_sqlite_value!(
379    i8,
380    i16,
381    i32,
382    i64,
383    isize,
384    u8,
385    u16,
386    u32,
387    u64,
388    usize,
389    f32,
390    f64,
391    bool,
392    String,
393    Box<String>,
394    Rc<String>,
395    Arc<String>,
396    Box<str>,
397    Rc<str>,
398    Arc<str>,
399    Box<Vec<u8>>,
400    Rc<Vec<u8>>,
401    Arc<Vec<u8>>,
402    Vec<u8>,
403    compact_str::CompactString,
404);
405
406#[cfg(feature = "uuid")]
407impl_try_from_owned_sqlite_value!(Uuid);
408
409#[cfg(feature = "bytes")]
410impl_try_from_owned_sqlite_value!(bytes::Bytes, bytes::BytesMut);
411
412#[cfg(feature = "smallvec")]
413impl<const N: usize> TryFrom<OwnedSQLiteValue> for smallvec::SmallVec<[u8; N]> {
414    type Error = DrizzleError;
415
416    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
417        value.convert()
418    }
419}
420
421#[cfg(feature = "arrayvec")]
422impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayString<N> {
423    type Error = DrizzleError;
424
425    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
426        match value {
427            OwnedSQLiteValue::Text(s) => Self::from(&s).map_err(|_| {
428                DrizzleError::ConversionError(
429                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
430                )
431            }),
432            _ => Err(DrizzleError::ConversionError(
433                format!("Cannot convert {value:?} to ArrayString").into(),
434            )),
435        }
436    }
437}
438
439#[cfg(feature = "arrayvec")]
440impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
441    type Error = DrizzleError;
442
443    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
444        match value {
445            OwnedSQLiteValue::Blob(bytes) => Self::try_from(bytes.as_ref()).map_err(|_| {
446                DrizzleError::ConversionError(
447                    format!(
448                        "Blob length {} exceeds ArrayVec capacity {}",
449                        bytes.len(),
450                        N
451                    )
452                    .into(),
453                )
454            }),
455            _ => Err(DrizzleError::ConversionError(
456                format!("Cannot convert {value:?} to ArrayVec<u8>").into(),
457            )),
458        }
459    }
460}
461
462//------------------------------------------------------------------------------
463// TryFrom<&OwnedSQLiteValue> implementations for borrowing without consuming
464// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
465//------------------------------------------------------------------------------
466
467/// Macro to implement `TryFrom`<&`OwnedSQLiteValue`> for types implementing `FromSQLiteValue`
468macro_rules! impl_try_from_owned_sqlite_value_ref {
469    ($($ty:ty),* $(,)?) => {
470        $(
471            impl TryFrom<&OwnedSQLiteValue> for $ty {
472                type Error = DrizzleError;
473
474                #[inline]
475                fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
476                    value.convert_ref()
477                }
478            }
479        )*
480    };
481}
482
483impl_try_from_owned_sqlite_value_ref!(
484    i8,
485    i16,
486    i32,
487    i64,
488    isize,
489    u8,
490    u16,
491    u32,
492    u64,
493    usize,
494    f32,
495    f64,
496    bool,
497    String,
498    Box<String>,
499    Rc<String>,
500    Arc<String>,
501    Box<str>,
502    Rc<str>,
503    Arc<str>,
504    Box<Vec<u8>>,
505    Rc<Vec<u8>>,
506    Arc<Vec<u8>>,
507    Vec<u8>,
508    compact_str::CompactString,
509);
510
511#[cfg(feature = "uuid")]
512impl_try_from_owned_sqlite_value_ref!(Uuid);
513
514#[cfg(feature = "bytes")]
515impl_try_from_owned_sqlite_value_ref!(bytes::Bytes, bytes::BytesMut);
516
517#[cfg(feature = "smallvec")]
518impl<const N: usize> TryFrom<&OwnedSQLiteValue> for smallvec::SmallVec<[u8; N]> {
519    type Error = DrizzleError;
520
521    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
522        value.convert_ref()
523    }
524}
525
526#[cfg(feature = "arrayvec")]
527impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayString<N> {
528    type Error = DrizzleError;
529
530    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
531        match value {
532            OwnedSQLiteValue::Text(s) => Self::from(s.as_str()).map_err(|_| {
533                DrizzleError::ConversionError(
534                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
535                )
536            }),
537            _ => Err(DrizzleError::ConversionError(
538                format!("Cannot convert {value:?} to ArrayString").into(),
539            )),
540        }
541    }
542}
543
544#[cfg(feature = "arrayvec")]
545impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
546    type Error = DrizzleError;
547
548    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
549        match value {
550            OwnedSQLiteValue::Blob(bytes) => Self::try_from(bytes.as_ref()).map_err(|_| {
551                DrizzleError::ConversionError(
552                    format!(
553                        "Blob length {} exceeds ArrayVec capacity {}",
554                        bytes.len(),
555                        N
556                    )
557                    .into(),
558                )
559            }),
560            _ => Err(DrizzleError::ConversionError(
561                format!("Cannot convert {value:?} to ArrayVec<u8>").into(),
562            )),
563        }
564    }
565}
566
567// --- Borrowed reference types (cannot use FromSQLiteValue) ---
568
569impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a str {
570    type Error = DrizzleError;
571
572    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
573        match value {
574            OwnedSQLiteValue::Text(s) => Ok(s.as_str()),
575            _ => Err(DrizzleError::ConversionError(
576                format!("Cannot convert {value:?} to &str").into(),
577            )),
578        }
579    }
580}
581
582impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a [u8] {
583    type Error = DrizzleError;
584
585    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
586        match value {
587            OwnedSQLiteValue::Blob(b) => Ok(b.as_ref()),
588            _ => Err(DrizzleError::ConversionError(
589                format!("Cannot convert {value:?} to &[u8]").into(),
590            )),
591        }
592    }
593}