drizzle_sqlite/values/owned/
conversions.rs

1//! From<T> and TryFrom<OwnedSQLiteValue> implementations
2
3use super::OwnedSQLiteValue;
4use drizzle_core::error::DrizzleError;
5use std::borrow::Cow;
6
7#[cfg(feature = "uuid")]
8use uuid::Uuid;
9
10//------------------------------------------------------------------------------
11// From<T> implementations
12// Macro-based to reduce boilerplate
13//------------------------------------------------------------------------------
14
15/// Macro to implement From<integer> for OwnedSQLiteValue (converts to INTEGER)
16macro_rules! impl_from_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(value as i64)
23                }
24            }
25
26            impl From<&$ty> for OwnedSQLiteValue {
27                #[inline]
28                fn from(value: &$ty) -> Self {
29                    OwnedSQLiteValue::Integer(*value as i64)
30                }
31            }
32        )*
33    };
34}
35
36/// Macro to implement From<float> for OwnedSQLiteValue (converts to REAL)
37macro_rules! impl_from_float_for_owned_sqlite_value {
38    ($($ty:ty),* $(,)?) => {
39        $(
40            impl From<$ty> for OwnedSQLiteValue {
41                #[inline]
42                fn from(value: $ty) -> Self {
43                    OwnedSQLiteValue::Real(value as f64)
44                }
45            }
46
47            impl From<&$ty> for OwnedSQLiteValue {
48                #[inline]
49                fn from(value: &$ty) -> Self {
50                    OwnedSQLiteValue::Real(*value as f64)
51                }
52            }
53        )*
54    };
55}
56
57// Integer types -> OwnedSQLiteValue::Integer
58impl_from_int_for_owned_sqlite_value!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, bool);
59
60// Float types -> OwnedSQLiteValue::Real
61impl_from_float_for_owned_sqlite_value!(f32, f64);
62
63// --- String Types ---
64
65impl From<&str> for OwnedSQLiteValue {
66    fn from(value: &str) -> Self {
67        OwnedSQLiteValue::Text(value.to_string())
68    }
69}
70
71impl From<Cow<'_, str>> for OwnedSQLiteValue {
72    fn from(value: Cow<'_, str>) -> Self {
73        OwnedSQLiteValue::Text(value.into_owned())
74    }
75}
76
77impl From<String> for OwnedSQLiteValue {
78    fn from(value: String) -> Self {
79        OwnedSQLiteValue::Text(value)
80    }
81}
82
83impl From<&String> for OwnedSQLiteValue {
84    fn from(value: &String) -> Self {
85        OwnedSQLiteValue::Text(value.clone())
86    }
87}
88
89// --- Binary Data ---
90
91impl From<&[u8]> for OwnedSQLiteValue {
92    fn from(value: &[u8]) -> Self {
93        OwnedSQLiteValue::Blob(value.to_vec().into_boxed_slice())
94    }
95}
96
97impl From<Cow<'_, [u8]>> for OwnedSQLiteValue {
98    fn from(value: Cow<'_, [u8]>) -> Self {
99        OwnedSQLiteValue::Blob(value.into_owned().into_boxed_slice())
100    }
101}
102
103impl From<Vec<u8>> for OwnedSQLiteValue {
104    fn from(value: Vec<u8>) -> Self {
105        OwnedSQLiteValue::Blob(value.into_boxed_slice())
106    }
107}
108
109// --- UUID ---
110
111#[cfg(feature = "uuid")]
112impl From<Uuid> for OwnedSQLiteValue {
113    fn from(value: Uuid) -> Self {
114        OwnedSQLiteValue::Blob(value.as_bytes().to_vec().into_boxed_slice())
115    }
116}
117
118#[cfg(feature = "uuid")]
119impl From<&Uuid> for OwnedSQLiteValue {
120    fn from(value: &Uuid) -> Self {
121        OwnedSQLiteValue::Blob(value.as_bytes().to_vec().into_boxed_slice())
122    }
123}
124
125#[cfg(feature = "arrayvec")]
126impl<const N: usize> From<arrayvec::ArrayString<N>> for OwnedSQLiteValue {
127    fn from(value: arrayvec::ArrayString<N>) -> Self {
128        OwnedSQLiteValue::Text(value.to_string())
129    }
130}
131
132#[cfg(feature = "arrayvec")]
133impl<const N: usize> From<arrayvec::ArrayVec<u8, N>> for OwnedSQLiteValue {
134    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
135        OwnedSQLiteValue::Blob(value.to_vec().into_boxed_slice())
136    }
137}
138
139// --- Option Types ---
140impl<T> From<Option<T>> for OwnedSQLiteValue
141where
142    T: TryInto<OwnedSQLiteValue>,
143{
144    fn from(value: Option<T>) -> Self {
145        match value {
146            Some(value) => value.try_into().unwrap_or(OwnedSQLiteValue::Null),
147            None => OwnedSQLiteValue::Null,
148        }
149    }
150}
151
152//------------------------------------------------------------------------------
153// TryFrom<OwnedSQLiteValue> implementations
154// Uses the FromSQLiteValue trait via convert() for unified conversion logic
155//------------------------------------------------------------------------------
156
157/// Macro to implement TryFrom<OwnedSQLiteValue> for types implementing FromSQLiteValue
158macro_rules! impl_try_from_owned_sqlite_value {
159    ($($ty:ty),* $(,)?) => {
160        $(
161            impl TryFrom<OwnedSQLiteValue> for $ty {
162                type Error = DrizzleError;
163
164                #[inline]
165                fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
166                    value.convert()
167                }
168            }
169        )*
170    };
171}
172
173impl_try_from_owned_sqlite_value!(
174    i8,
175    i16,
176    i32,
177    i64,
178    isize,
179    u8,
180    u16,
181    u32,
182    u64,
183    usize,
184    f32,
185    f64,
186    bool,
187    String,
188    Vec<u8>,
189);
190
191#[cfg(feature = "uuid")]
192impl_try_from_owned_sqlite_value!(Uuid);
193
194#[cfg(feature = "arrayvec")]
195impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayString<N> {
196    type Error = DrizzleError;
197
198    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
199        match value {
200            OwnedSQLiteValue::Text(s) => arrayvec::ArrayString::from(&s).map_err(|_| {
201                DrizzleError::ConversionError(
202                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
203                )
204            }),
205            _ => Err(DrizzleError::ConversionError(
206                format!("Cannot convert {:?} to ArrayString", value).into(),
207            )),
208        }
209    }
210}
211
212#[cfg(feature = "arrayvec")]
213impl<const N: usize> TryFrom<OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
214    type Error = DrizzleError;
215
216    fn try_from(value: OwnedSQLiteValue) -> Result<Self, Self::Error> {
217        match value {
218            OwnedSQLiteValue::Blob(bytes) => {
219                arrayvec::ArrayVec::try_from(bytes.as_ref()).map_err(|_| {
220                    DrizzleError::ConversionError(
221                        format!(
222                            "Blob length {} exceeds ArrayVec capacity {}",
223                            bytes.len(),
224                            N
225                        )
226                        .into(),
227                    )
228                })
229            }
230            _ => Err(DrizzleError::ConversionError(
231                format!("Cannot convert {:?} to ArrayVec<u8>", value).into(),
232            )),
233        }
234    }
235}
236
237//------------------------------------------------------------------------------
238// TryFrom<&OwnedSQLiteValue> implementations for borrowing without consuming
239// Uses the FromSQLiteValue trait via convert_ref() for unified conversion logic
240//------------------------------------------------------------------------------
241
242/// Macro to implement TryFrom<&OwnedSQLiteValue> for types implementing FromSQLiteValue
243macro_rules! impl_try_from_owned_sqlite_value_ref {
244    ($($ty:ty),* $(,)?) => {
245        $(
246            impl TryFrom<&OwnedSQLiteValue> for $ty {
247                type Error = DrizzleError;
248
249                #[inline]
250                fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
251                    value.convert_ref()
252                }
253            }
254        )*
255    };
256}
257
258impl_try_from_owned_sqlite_value_ref!(
259    i8,
260    i16,
261    i32,
262    i64,
263    isize,
264    u8,
265    u16,
266    u32,
267    u64,
268    usize,
269    f32,
270    f64,
271    bool,
272    String,
273    Vec<u8>,
274);
275
276#[cfg(feature = "uuid")]
277impl_try_from_owned_sqlite_value_ref!(Uuid);
278
279#[cfg(feature = "arrayvec")]
280impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayString<N> {
281    type Error = DrizzleError;
282
283    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
284        match value {
285            OwnedSQLiteValue::Text(s) => arrayvec::ArrayString::from(s.as_str()).map_err(|_| {
286                DrizzleError::ConversionError(
287                    format!("Text length {} exceeds ArrayString capacity {}", s.len(), N).into(),
288                )
289            }),
290            _ => Err(DrizzleError::ConversionError(
291                format!("Cannot convert {:?} to ArrayString", value).into(),
292            )),
293        }
294    }
295}
296
297#[cfg(feature = "arrayvec")]
298impl<const N: usize> TryFrom<&OwnedSQLiteValue> for arrayvec::ArrayVec<u8, N> {
299    type Error = DrizzleError;
300
301    fn try_from(value: &OwnedSQLiteValue) -> Result<Self, Self::Error> {
302        match value {
303            OwnedSQLiteValue::Blob(bytes) => {
304                arrayvec::ArrayVec::try_from(bytes.as_ref()).map_err(|_| {
305                    DrizzleError::ConversionError(
306                        format!(
307                            "Blob length {} exceeds ArrayVec capacity {}",
308                            bytes.len(),
309                            N
310                        )
311                        .into(),
312                    )
313                })
314            }
315            _ => Err(DrizzleError::ConversionError(
316                format!("Cannot convert {:?} to ArrayVec<u8>", value).into(),
317            )),
318        }
319    }
320}
321
322// --- Borrowed reference types (cannot use FromSQLiteValue) ---
323
324impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a str {
325    type Error = DrizzleError;
326
327    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
328        match value {
329            OwnedSQLiteValue::Text(s) => Ok(s.as_str()),
330            _ => Err(DrizzleError::ConversionError(
331                format!("Cannot convert {:?} to &str", value).into(),
332            )),
333        }
334    }
335}
336
337impl<'a> TryFrom<&'a OwnedSQLiteValue> for &'a [u8] {
338    type Error = DrizzleError;
339
340    fn try_from(value: &'a OwnedSQLiteValue) -> Result<Self, Self::Error> {
341        match value {
342            OwnedSQLiteValue::Blob(b) => Ok(b.as_ref()),
343            _ => Err(DrizzleError::ConversionError(
344                format!("Cannot convert {:?} to &[u8]", value).into(),
345            )),
346        }
347    }
348}