Skip to main content

drizzle_sqlite/values/
conversions.rs

1//! From and TryFrom implementations for SQLiteValue
2
3use super::{OwnedSQLiteValue, SQLiteValue};
4use drizzle_core::{error::DrizzleError, sql::SQL, traits::ToSQL};
5use std::{borrow::Cow, rc::Rc, sync::Arc};
6
7#[cfg(feature = "uuid")]
8use uuid::Uuid;
9
10//------------------------------------------------------------------------------
11// ToSQL Implementation
12//------------------------------------------------------------------------------
13
14impl<'a> ToSQL<'a, SQLiteValue<'a>> for SQLiteValue<'a> {
15    fn to_sql(&self) -> SQL<'a, SQLiteValue<'a>> {
16        SQL::param(self.clone())
17    }
18}
19
20//------------------------------------------------------------------------------
21// From OwnedSQLiteValue
22//------------------------------------------------------------------------------
23
24impl<'a> From<OwnedSQLiteValue> for SQLiteValue<'a> {
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 SQLiteValue<'a>> for SQLiteValue<'a> {
49    fn from(value: &'a SQLiteValue<'a>) -> 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, SQLiteValue<'a>>> for SQLiteValue<'a> {
61    fn from(value: Cow<'a, SQLiteValue<'a>>) -> 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, SQLiteValue<'a>>> for SQLiteValue<'a> {
70    fn from(value: &'a Cow<'a, SQLiteValue<'a>>) -> 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/// Macro to implement From<integer> for SQLiteValue (converts to INTEGER)
84macro_rules! impl_from_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(value as i64)
91                }
92            }
93
94            impl<'a> From<&$ty> for SQLiteValue<'a> {
95                #[inline]
96                fn from(value: &$ty) -> Self {
97                    SQLiteValue::Integer(*value as i64)
98                }
99            }
100        )*
101    };
102}
103
104/// Macro to implement From<float> for SQLiteValue (converts to REAL)
105macro_rules! impl_from_float_for_sqlite_value {
106    ($($ty:ty),* $(,)?) => {
107        $(
108            impl<'a> From<$ty> for SQLiteValue<'a> {
109                #[inline]
110                fn from(value: $ty) -> Self {
111                    SQLiteValue::Real(value as f64)
112                }
113            }
114
115            impl<'a> From<&$ty> for SQLiteValue<'a> {
116                #[inline]
117                fn from(value: &$ty) -> Self {
118                    SQLiteValue::Real(*value as f64)
119                }
120            }
121        )*
122    };
123}
124
125// Integer types -> SQLiteValue::Integer
126impl_from_int_for_sqlite_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, bool);
127
128// Float types -> SQLiteValue::Real
129impl_from_float_for_sqlite_value!(f32, f64);
130
131// --- String Types ---
132
133impl<'a> From<&'a str> for SQLiteValue<'a> {
134    fn from(value: &'a str) -> Self {
135        SQLiteValue::Text(Cow::Borrowed(value))
136    }
137}
138
139impl<'a> From<Cow<'a, str>> for SQLiteValue<'a> {
140    fn from(value: Cow<'a, str>) -> Self {
141        SQLiteValue::Text(value)
142    }
143}
144
145impl<'a> From<String> for SQLiteValue<'a> {
146    fn from(value: String) -> Self {
147        SQLiteValue::Text(Cow::Owned(value))
148    }
149}
150
151impl<'a> From<&'a String> for SQLiteValue<'a> {
152    fn from(value: &'a String) -> Self {
153        SQLiteValue::Text(Cow::Borrowed(value))
154    }
155}
156
157impl<'a> From<Box<String>> for SQLiteValue<'a> {
158    fn from(value: Box<String>) -> Self {
159        SQLiteValue::Text(Cow::Owned(*value))
160    }
161}
162
163impl<'a> From<&'a Box<String>> for SQLiteValue<'a> {
164    fn from(value: &'a Box<String>) -> Self {
165        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
166    }
167}
168
169impl<'a> From<Rc<String>> for SQLiteValue<'a> {
170    fn from(value: Rc<String>) -> Self {
171        SQLiteValue::Text(Cow::Owned(value.as_ref().clone()))
172    }
173}
174
175impl<'a> From<&'a Rc<String>> for SQLiteValue<'a> {
176    fn from(value: &'a Rc<String>) -> Self {
177        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
178    }
179}
180
181impl<'a> From<Arc<String>> for SQLiteValue<'a> {
182    fn from(value: Arc<String>) -> Self {
183        SQLiteValue::Text(Cow::Owned(value.as_ref().clone()))
184    }
185}
186
187impl<'a> From<&'a Arc<String>> for SQLiteValue<'a> {
188    fn from(value: &'a Arc<String>) -> Self {
189        SQLiteValue::Text(Cow::Borrowed(value.as_str()))
190    }
191}
192
193impl<'a> From<Box<str>> for SQLiteValue<'a> {
194    fn from(value: Box<str>) -> Self {
195        SQLiteValue::Text(Cow::Owned(value.into()))
196    }
197}
198
199impl<'a> From<&'a Box<str>> for SQLiteValue<'a> {
200    fn from(value: &'a Box<str>) -> Self {
201        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
202    }
203}
204
205impl<'a> From<Rc<str>> for SQLiteValue<'a> {
206    fn from(value: Rc<str>) -> Self {
207        SQLiteValue::Text(Cow::Owned(value.as_ref().to_string()))
208    }
209}
210
211impl<'a> From<&'a Rc<str>> for SQLiteValue<'a> {
212    fn from(value: &'a Rc<str>) -> Self {
213        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
214    }
215}
216
217impl<'a> From<Arc<str>> for SQLiteValue<'a> {
218    fn from(value: Arc<str>) -> Self {
219        SQLiteValue::Text(Cow::Owned(value.as_ref().to_string()))
220    }
221}
222
223impl<'a> From<&'a Arc<str>> for SQLiteValue<'a> {
224    fn from(value: &'a Arc<str>) -> Self {
225        SQLiteValue::Text(Cow::Borrowed(value.as_ref()))
226    }
227}
228
229// --- ArrayString ---
230
231#[cfg(feature = "arrayvec")]
232impl<'a, const N: usize> From<arrayvec::ArrayString<N>> for SQLiteValue<'a> {
233    fn from(value: arrayvec::ArrayString<N>) -> Self {
234        SQLiteValue::Text(Cow::Owned(value.to_string()))
235    }
236}
237
238#[cfg(feature = "arrayvec")]
239impl<'a, const N: usize> From<&arrayvec::ArrayString<N>> for SQLiteValue<'a> {
240    fn from(value: &arrayvec::ArrayString<N>) -> Self {
241        SQLiteValue::Text(Cow::Owned(value.as_str().to_owned()))
242    }
243}
244
245// --- Binary Data ---
246
247impl<'a> From<&'a [u8]> for SQLiteValue<'a> {
248    fn from(value: &'a [u8]) -> Self {
249        SQLiteValue::Blob(Cow::Borrowed(value))
250    }
251}
252
253impl<'a> From<Cow<'a, [u8]>> for SQLiteValue<'a> {
254    fn from(value: Cow<'a, [u8]>) -> Self {
255        SQLiteValue::Blob(value)
256    }
257}
258
259impl<'a> From<Vec<u8>> for SQLiteValue<'a> {
260    fn from(value: Vec<u8>) -> Self {
261        SQLiteValue::Blob(Cow::Owned(value))
262    }
263}
264
265impl<'a> From<Box<Vec<u8>>> for SQLiteValue<'a> {
266    fn from(value: Box<Vec<u8>>) -> Self {
267        SQLiteValue::Blob(Cow::Owned(*value))
268    }
269}
270
271impl<'a> From<&'a Box<Vec<u8>>> for SQLiteValue<'a> {
272    fn from(value: &'a Box<Vec<u8>>) -> Self {
273        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
274    }
275}
276
277impl<'a> From<Rc<Vec<u8>>> for SQLiteValue<'a> {
278    fn from(value: Rc<Vec<u8>>) -> Self {
279        SQLiteValue::Blob(Cow::Owned(value.as_ref().clone()))
280    }
281}
282
283impl<'a> From<&'a Rc<Vec<u8>>> for SQLiteValue<'a> {
284    fn from(value: &'a Rc<Vec<u8>>) -> Self {
285        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
286    }
287}
288
289impl<'a> From<Arc<Vec<u8>>> for SQLiteValue<'a> {
290    fn from(value: Arc<Vec<u8>>) -> Self {
291        SQLiteValue::Blob(Cow::Owned(value.as_ref().clone()))
292    }
293}
294
295impl<'a> From<&'a Arc<Vec<u8>>> for SQLiteValue<'a> {
296    fn from(value: &'a Arc<Vec<u8>>) -> Self {
297        SQLiteValue::Blob(Cow::Borrowed(value.as_slice()))
298    }
299}
300
301// --- ArrayVec<u8, N> ---
302
303#[cfg(feature = "arrayvec")]
304impl<'a, const N: usize> From<arrayvec::ArrayVec<u8, N>> for SQLiteValue<'a> {
305    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
306        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
307    }
308}
309
310#[cfg(feature = "arrayvec")]
311impl<'a, const N: usize> From<&arrayvec::ArrayVec<u8, N>> for SQLiteValue<'a> {
312    fn from(value: &arrayvec::ArrayVec<u8, N>) -> Self {
313        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
314    }
315}
316
317// --- UUID ---
318
319#[cfg(feature = "uuid")]
320impl<'a> From<Uuid> for SQLiteValue<'a> {
321    fn from(value: Uuid) -> Self {
322        SQLiteValue::Blob(Cow::Owned(value.as_bytes().to_vec()))
323    }
324}
325
326#[cfg(feature = "uuid")]
327impl<'a> From<&'a Uuid> for SQLiteValue<'a> {
328    fn from(value: &'a Uuid) -> Self {
329        SQLiteValue::Blob(Cow::Borrowed(value.as_bytes()))
330    }
331}
332
333// --- Option Types ---
334impl<'a, T> From<Option<T>> for SQLiteValue<'a>
335where
336    T: TryInto<SQLiteValue<'a>>,
337{
338    fn from(value: Option<T>) -> Self {
339        match value {
340            Some(value) => value.try_into().unwrap_or(SQLiteValue::Null),
341            None => SQLiteValue::Null,
342        }
343    }
344}
345
346// --- Cow integration for SQL struct ---
347impl<'a> From<SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
348    fn from(value: SQLiteValue<'a>) -> Self {
349        Cow::Owned(value)
350    }
351}
352
353impl<'a> From<&'a SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
354    fn from(value: &'a SQLiteValue<'a>) -> Self {
355        Cow::Borrowed(value)
356    }
357}
358
359//------------------------------------------------------------------------------
360// TryFrom<SQLiteValue> implementations
361// Uses the FromSQLiteValue trait via convert() for unified conversion logic
362//------------------------------------------------------------------------------
363
364/// Macro to implement TryFrom<SQLiteValue> for types implementing FromSQLiteValue
365macro_rules! impl_try_from_sqlite_value {
366    ($($ty:ty),* $(,)?) => {
367        $(
368            impl<'a> TryFrom<SQLiteValue<'a>> for $ty {
369                type Error = DrizzleError;
370
371                #[inline]
372                fn try_from(value: SQLiteValue<'a>) -> Result<Self, Self::Error> {
373                    value.convert()
374                }
375            }
376        )*
377    };
378}
379
380impl_try_from_sqlite_value!(
381    i8,
382    i16,
383    i32,
384    i64,
385    isize,
386    u8,
387    u16,
388    u32,
389    u64,
390    usize,
391    f32,
392    f64,
393    bool,
394    String,
395    Box<String>,
396    Rc<String>,
397    Arc<String>,
398    Box<str>,
399    Rc<str>,
400    Arc<str>,
401    Box<Vec<u8>>,
402    Rc<Vec<u8>>,
403    Arc<Vec<u8>>,
404    Vec<u8>,
405);
406
407#[cfg(feature = "uuid")]
408impl_try_from_sqlite_value!(Uuid);
409
410//------------------------------------------------------------------------------
411// TryFrom<&SQLiteValue> implementations for borrowing without consuming
412// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
413//------------------------------------------------------------------------------
414
415/// Macro to implement TryFrom<&SQLiteValue> for types implementing FromSQLiteValue
416macro_rules! impl_try_from_sqlite_value_ref {
417    ($($ty:ty),* $(,)?) => {
418        $(
419            impl<'a> TryFrom<&SQLiteValue<'a>> for $ty {
420                type Error = DrizzleError;
421
422                #[inline]
423                fn try_from(value: &SQLiteValue<'a>) -> Result<Self, Self::Error> {
424                    value.convert_ref()
425                }
426            }
427        )*
428    };
429}
430
431impl_try_from_sqlite_value_ref!(
432    i8,
433    i16,
434    i32,
435    i64,
436    isize,
437    u8,
438    u16,
439    u32,
440    u64,
441    usize,
442    f32,
443    f64,
444    bool,
445    String,
446    Box<String>,
447    Rc<String>,
448    Arc<String>,
449    Box<str>,
450    Rc<str>,
451    Arc<str>,
452    Box<Vec<u8>>,
453    Rc<Vec<u8>>,
454    Arc<Vec<u8>>,
455    Vec<u8>,
456);
457
458#[cfg(feature = "uuid")]
459impl_try_from_sqlite_value_ref!(Uuid);
460
461// --- Borrowed reference types (cannot use FromSQLiteValue) ---
462
463impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a str {
464    type Error = DrizzleError;
465
466    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
467        match value {
468            SQLiteValue::Text(cow) => Ok(cow.as_ref()),
469            _ => Err(DrizzleError::ConversionError(
470                format!("Cannot convert {:?} to &str", value).into(),
471            )),
472        }
473    }
474}
475
476impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a [u8] {
477    type Error = DrizzleError;
478
479    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
480        match value {
481            SQLiteValue::Blob(cow) => Ok(cow.as_ref()),
482            _ => Err(DrizzleError::ConversionError(
483                format!("Cannot convert {:?} to &[u8]", value).into(),
484            )),
485        }
486    }
487}