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;
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
157// --- ArrayString ---
158
159#[cfg(feature = "arrayvec")]
160impl<'a, const N: usize> From<arrayvec::ArrayString<N>> for SQLiteValue<'a> {
161    fn from(value: arrayvec::ArrayString<N>) -> Self {
162        SQLiteValue::Text(Cow::Owned(value.to_string()))
163    }
164}
165
166#[cfg(feature = "arrayvec")]
167impl<'a, const N: usize> From<&arrayvec::ArrayString<N>> for SQLiteValue<'a> {
168    fn from(value: &arrayvec::ArrayString<N>) -> Self {
169        SQLiteValue::Text(Cow::Owned(value.as_str().to_owned()))
170    }
171}
172
173// --- Binary Data ---
174
175impl<'a> From<&'a [u8]> for SQLiteValue<'a> {
176    fn from(value: &'a [u8]) -> Self {
177        SQLiteValue::Blob(Cow::Borrowed(value))
178    }
179}
180
181impl<'a> From<Cow<'a, [u8]>> for SQLiteValue<'a> {
182    fn from(value: Cow<'a, [u8]>) -> Self {
183        SQLiteValue::Blob(value)
184    }
185}
186
187impl<'a> From<Vec<u8>> for SQLiteValue<'a> {
188    fn from(value: Vec<u8>) -> Self {
189        SQLiteValue::Blob(Cow::Owned(value))
190    }
191}
192
193// --- ArrayVec<u8, N> ---
194
195#[cfg(feature = "arrayvec")]
196impl<'a, const N: usize> From<arrayvec::ArrayVec<u8, N>> for SQLiteValue<'a> {
197    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
198        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
199    }
200}
201
202#[cfg(feature = "arrayvec")]
203impl<'a, const N: usize> From<&arrayvec::ArrayVec<u8, N>> for SQLiteValue<'a> {
204    fn from(value: &arrayvec::ArrayVec<u8, N>) -> Self {
205        SQLiteValue::Blob(Cow::Owned(value.to_vec()))
206    }
207}
208
209// --- UUID ---
210
211#[cfg(feature = "uuid")]
212impl<'a> From<Uuid> for SQLiteValue<'a> {
213    fn from(value: Uuid) -> Self {
214        SQLiteValue::Blob(Cow::Owned(value.as_bytes().to_vec()))
215    }
216}
217
218#[cfg(feature = "uuid")]
219impl<'a> From<&'a Uuid> for SQLiteValue<'a> {
220    fn from(value: &'a Uuid) -> Self {
221        SQLiteValue::Blob(Cow::Borrowed(value.as_bytes()))
222    }
223}
224
225// --- Option Types ---
226impl<'a, T> From<Option<T>> for SQLiteValue<'a>
227where
228    T: TryInto<SQLiteValue<'a>>,
229{
230    fn from(value: Option<T>) -> Self {
231        match value {
232            Some(value) => value.try_into().unwrap_or(SQLiteValue::Null),
233            None => SQLiteValue::Null,
234        }
235    }
236}
237
238// --- Cow integration for SQL struct ---
239impl<'a> From<SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
240    fn from(value: SQLiteValue<'a>) -> Self {
241        Cow::Owned(value)
242    }
243}
244
245impl<'a> From<&'a SQLiteValue<'a>> for Cow<'a, SQLiteValue<'a>> {
246    fn from(value: &'a SQLiteValue<'a>) -> Self {
247        Cow::Borrowed(value)
248    }
249}
250
251//------------------------------------------------------------------------------
252// TryFrom<SQLiteValue> implementations
253// Uses the FromSQLiteValue trait via convert() for unified conversion logic
254//------------------------------------------------------------------------------
255
256/// Macro to implement TryFrom<SQLiteValue> for types implementing FromSQLiteValue
257macro_rules! impl_try_from_sqlite_value {
258    ($($ty:ty),* $(,)?) => {
259        $(
260            impl<'a> TryFrom<SQLiteValue<'a>> for $ty {
261                type Error = DrizzleError;
262
263                #[inline]
264                fn try_from(value: SQLiteValue<'a>) -> Result<Self, Self::Error> {
265                    value.convert()
266                }
267            }
268        )*
269    };
270}
271
272impl_try_from_sqlite_value!(
273    i8,
274    i16,
275    i32,
276    i64,
277    isize,
278    u8,
279    u16,
280    u32,
281    u64,
282    usize,
283    f32,
284    f64,
285    bool,
286    String,
287    Vec<u8>,
288);
289
290#[cfg(feature = "uuid")]
291impl_try_from_sqlite_value!(Uuid);
292
293//------------------------------------------------------------------------------
294// TryFrom<&SQLiteValue> implementations for borrowing without consuming
295// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
296//------------------------------------------------------------------------------
297
298/// Macro to implement TryFrom<&SQLiteValue> for types implementing FromSQLiteValue
299macro_rules! impl_try_from_sqlite_value_ref {
300    ($($ty:ty),* $(,)?) => {
301        $(
302            impl<'a> TryFrom<&SQLiteValue<'a>> for $ty {
303                type Error = DrizzleError;
304
305                #[inline]
306                fn try_from(value: &SQLiteValue<'a>) -> Result<Self, Self::Error> {
307                    value.convert_ref()
308                }
309            }
310        )*
311    };
312}
313
314impl_try_from_sqlite_value_ref!(
315    i8,
316    i16,
317    i32,
318    i64,
319    isize,
320    u8,
321    u16,
322    u32,
323    u64,
324    usize,
325    f32,
326    f64,
327    bool,
328    String,
329    Vec<u8>,
330);
331
332#[cfg(feature = "uuid")]
333impl_try_from_sqlite_value_ref!(Uuid);
334
335// --- Borrowed reference types (cannot use FromSQLiteValue) ---
336
337impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a str {
338    type Error = DrizzleError;
339
340    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
341        match value {
342            SQLiteValue::Text(cow) => Ok(cow.as_ref()),
343            _ => Err(DrizzleError::ConversionError(
344                format!("Cannot convert {:?} to &str", value).into(),
345            )),
346        }
347    }
348}
349
350impl<'a> TryFrom<&'a SQLiteValue<'a>> for &'a [u8] {
351    type Error = DrizzleError;
352
353    fn try_from(value: &'a SQLiteValue<'a>) -> Result<Self, Self::Error> {
354        match value {
355            SQLiteValue::Blob(cow) => Ok(cow.as_ref()),
356            _ => Err(DrizzleError::ConversionError(
357                format!("Cannot convert {:?} to &[u8]", value).into(),
358            )),
359        }
360    }
361}