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 ---
335impl<T> From<Option<T>> for OwnedSQLiteValue
336where
337    T: TryInto<Self>,
338{
339    fn from(value: Option<T>) -> Self {
340        value.map_or(Self::Null, |v| v.try_into().unwrap_or(Self::Null))
341    }
342}
343
344//------------------------------------------------------------------------------
345// TryFrom<OwnedSQLiteValue> implementations
346// Uses the FromSQLiteValue trait via convert() for unified conversion logic
347//------------------------------------------------------------------------------
348
349/// Macro to implement `TryFrom`<OwnedSQLiteValue> for types implementing `FromSQLiteValue`
350macro_rules! impl_try_from_owned_sqlite_value {
351    ($($ty:ty),* $(,)?) => {
352        $(
353            impl TryFrom<OwnedSQLiteValue> for $ty {
354                type Error = DrizzleError;
355
356                #[inline]
357                fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
358                    value.convert()
359                }
360            }
361        )*
362    };
363}
364
365impl_try_from_owned_sqlite_value!(
366    i8,
367    i16,
368    i32,
369    i64,
370    isize,
371    u8,
372    u16,
373    u32,
374    u64,
375    usize,
376    f32,
377    f64,
378    bool,
379    String,
380    Box<String>,
381    Rc<String>,
382    Arc<String>,
383    Box<str>,
384    Rc<str>,
385    Arc<str>,
386    Box<Vec<u8>>,
387    Rc<Vec<u8>>,
388    Arc<Vec<u8>>,
389    Vec<u8>,
390    compact_str::CompactString,
391);
392
393#[cfg(feature = "uuid")]
394impl_try_from_owned_sqlite_value!(Uuid);
395
396#[cfg(feature = "bytes")]
397impl_try_from_owned_sqlite_value!(bytes::Bytes, bytes::BytesMut);
398
399#[cfg(feature = "smallvec")]
400impl<const N: usize> TryFrom<OwnedSQLiteValue> for smallvec::SmallVec<[u8; N]> {
401    type Error = DrizzleError;
402
403    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
404        value.convert()
405    }
406}
407
408#[cfg(feature = "arrayvec")]
409impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayString<N> {
410    type Error = DrizzleError;
411
412    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
413        match value {
414            OwnedSQLiteValue::Text(s) => Self::from(&s).map_err(|_| {
415                DrizzleError::ConversionError(
416                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
417                )
418            }),
419            _ => Err(DrizzleError::ConversionError(
420                format!("Cannot convert {value:?} to ArrayString").into(),
421            )),
422        }
423    }
424}
425
426#[cfg(feature = "arrayvec")]
427impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
428    type Error = DrizzleError;
429
430    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
431        match value {
432            OwnedSQLiteValue::Blob(bytes) => Self::try_from(bytes.as_ref()).map_err(|_| {
433                DrizzleError::ConversionError(
434                    format!(
435                        "Blob length {} exceeds ArrayVec capacity {}",
436                        bytes.len(),
437                        N
438                    )
439                    .into(),
440                )
441            }),
442            _ => Err(DrizzleError::ConversionError(
443                format!("Cannot convert {value:?} to ArrayVec<u8>").into(),
444            )),
445        }
446    }
447}
448
449//------------------------------------------------------------------------------
450// TryFrom<&OwnedSQLiteValue> implementations for borrowing without consuming
451// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
452//------------------------------------------------------------------------------
453
454/// Macro to implement `TryFrom`<&`OwnedSQLiteValue`> for types implementing `FromSQLiteValue`
455macro_rules! impl_try_from_owned_sqlite_value_ref {
456    ($($ty:ty),* $(,)?) => {
457        $(
458            impl TryFrom<&OwnedSQLiteValue> for $ty {
459                type Error = DrizzleError;
460
461                #[inline]
462                fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
463                    value.convert_ref()
464                }
465            }
466        )*
467    };
468}
469
470impl_try_from_owned_sqlite_value_ref!(
471    i8,
472    i16,
473    i32,
474    i64,
475    isize,
476    u8,
477    u16,
478    u32,
479    u64,
480    usize,
481    f32,
482    f64,
483    bool,
484    String,
485    Box<String>,
486    Rc<String>,
487    Arc<String>,
488    Box<str>,
489    Rc<str>,
490    Arc<str>,
491    Box<Vec<u8>>,
492    Rc<Vec<u8>>,
493    Arc<Vec<u8>>,
494    Vec<u8>,
495    compact_str::CompactString,
496);
497
498#[cfg(feature = "uuid")]
499impl_try_from_owned_sqlite_value_ref!(Uuid);
500
501#[cfg(feature = "bytes")]
502impl_try_from_owned_sqlite_value_ref!(bytes::Bytes, bytes::BytesMut);
503
504#[cfg(feature = "smallvec")]
505impl<const N: usize> TryFrom<&OwnedSQLiteValue> for smallvec::SmallVec<[u8; N]> {
506    type Error = DrizzleError;
507
508    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
509        value.convert_ref()
510    }
511}
512
513#[cfg(feature = "arrayvec")]
514impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayString<N> {
515    type Error = DrizzleError;
516
517    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
518        match value {
519            OwnedSQLiteValue::Text(s) => Self::from(s.as_str()).map_err(|_| {
520                DrizzleError::ConversionError(
521                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
522                )
523            }),
524            _ => Err(DrizzleError::ConversionError(
525                format!("Cannot convert {value:?} to ArrayString").into(),
526            )),
527        }
528    }
529}
530
531#[cfg(feature = "arrayvec")]
532impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
533    type Error = DrizzleError;
534
535    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
536        match value {
537            OwnedSQLiteValue::Blob(bytes) => Self::try_from(bytes.as_ref()).map_err(|_| {
538                DrizzleError::ConversionError(
539                    format!(
540                        "Blob length {} exceeds ArrayVec capacity {}",
541                        bytes.len(),
542                        N
543                    )
544                    .into(),
545                )
546            }),
547            _ => Err(DrizzleError::ConversionError(
548                format!("Cannot convert {value:?} to ArrayVec<u8>").into(),
549            )),
550        }
551    }
552}
553
554// --- Borrowed reference types (cannot use FromSQLiteValue) ---
555
556impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a str {
557    type Error = DrizzleError;
558
559    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
560        match value {
561            OwnedSQLiteValue::Text(s) => Ok(s.as_str()),
562            _ => Err(DrizzleError::ConversionError(
563                format!("Cannot convert {value:?} to &str").into(),
564            )),
565        }
566    }
567}
568
569impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a [u8] {
570    type Error = DrizzleError;
571
572    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
573        match value {
574            OwnedSQLiteValue::Blob(b) => Ok(b.as_ref()),
575            _ => Err(DrizzleError::ConversionError(
576                format!("Cannot convert {value:?} to &[u8]").into(),
577            )),
578        }
579    }
580}