drizzle_postgres/values/
conversions.rs

1//! From<T> and TryFrom<PostgresValue> implementations
2
3use super::PostgresValue;
4use drizzle_core::error::DrizzleError;
5use std::borrow::Cow;
6
7#[cfg(feature = "uuid")]
8use uuid::Uuid;
9
10#[cfg(feature = "chrono")]
11use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
12
13#[cfg(feature = "cidr")]
14use cidr::{IpCidr, IpInet};
15
16#[cfg(feature = "geo-types")]
17use geo_types::{LineString, Point, Rect};
18
19#[cfg(feature = "bit-vec")]
20use bit_vec::BitVec;
21
22//------------------------------------------------------------------------------
23// From<T> implementations
24//------------------------------------------------------------------------------
25
26// --- Integer Types ---
27
28// i8 → SMALLINT (PostgreSQL doesn't have a native i8 type)
29impl<'a> From<i8> for PostgresValue<'a> {
30    fn from(value: i8) -> Self {
31        PostgresValue::Smallint(value as i16)
32    }
33}
34
35impl<'a> From<&'a i8> for PostgresValue<'a> {
36    fn from(value: &'a i8) -> Self {
37        PostgresValue::Smallint(*value as i16)
38    }
39}
40
41// i16 (SMALLINT)
42impl<'a> From<i16> for PostgresValue<'a> {
43    fn from(value: i16) -> Self {
44        PostgresValue::Smallint(value)
45    }
46}
47
48impl<'a> From<&'a i16> for PostgresValue<'a> {
49    fn from(value: &'a i16) -> Self {
50        PostgresValue::Smallint(*value)
51    }
52}
53
54// i32 (INTEGER)
55impl<'a> From<i32> for PostgresValue<'a> {
56    fn from(value: i32) -> Self {
57        PostgresValue::Integer(value)
58    }
59}
60
61impl<'a> From<&'a i32> for PostgresValue<'a> {
62    fn from(value: &'a i32) -> Self {
63        PostgresValue::Integer(*value)
64    }
65}
66
67// i64 (BIGINT)
68impl<'a> From<i64> for PostgresValue<'a> {
69    fn from(value: i64) -> Self {
70        PostgresValue::Bigint(value)
71    }
72}
73
74impl<'a> From<&'a i64> for PostgresValue<'a> {
75    fn from(value: &'a i64) -> Self {
76        PostgresValue::Bigint(*value)
77    }
78}
79
80// u8 → SMALLINT (PostgreSQL doesn't have unsigned types)
81impl<'a> From<u8> for PostgresValue<'a> {
82    fn from(value: u8) -> Self {
83        PostgresValue::Smallint(value as i16)
84    }
85}
86
87impl<'a> From<&'a u8> for PostgresValue<'a> {
88    fn from(value: &'a u8) -> Self {
89        PostgresValue::Smallint(*value as i16)
90    }
91}
92
93// u16 → INTEGER (cast to larger signed type)
94impl<'a> From<u16> for PostgresValue<'a> {
95    fn from(value: u16) -> Self {
96        PostgresValue::Integer(value as i32)
97    }
98}
99
100impl<'a> From<&'a u16> for PostgresValue<'a> {
101    fn from(value: &'a u16) -> Self {
102        PostgresValue::Integer(*value as i32)
103    }
104}
105
106// u32 → BIGINT (cast to larger signed type since u32 max > i32 max)
107impl<'a> From<u32> for PostgresValue<'a> {
108    fn from(value: u32) -> Self {
109        PostgresValue::Bigint(value as i64)
110    }
111}
112
113impl<'a> From<&'a u32> for PostgresValue<'a> {
114    fn from(value: &'a u32) -> Self {
115        PostgresValue::Bigint(*value as i64)
116    }
117}
118
119// u64 → BIGINT (cast with potential overflow since u64 max > i64 max)
120impl<'a> From<u64> for PostgresValue<'a> {
121    fn from(value: u64) -> Self {
122        PostgresValue::Bigint(value as i64)
123    }
124}
125
126impl<'a> From<&'a u64> for PostgresValue<'a> {
127    fn from(value: &'a u64) -> Self {
128        PostgresValue::Bigint(*value as i64)
129    }
130}
131
132// isize → BIGINT (platform-dependent size)
133impl<'a> From<isize> for PostgresValue<'a> {
134    fn from(value: isize) -> Self {
135        PostgresValue::Bigint(value as i64)
136    }
137}
138
139impl<'a> From<&'a isize> for PostgresValue<'a> {
140    fn from(value: &'a isize) -> Self {
141        PostgresValue::Bigint(*value as i64)
142    }
143}
144
145// usize → BIGINT (platform-dependent size)
146impl<'a> From<usize> for PostgresValue<'a> {
147    fn from(value: usize) -> Self {
148        PostgresValue::Bigint(value as i64)
149    }
150}
151
152impl<'a> From<&'a usize> for PostgresValue<'a> {
153    fn from(value: &'a usize) -> Self {
154        PostgresValue::Bigint(*value as i64)
155    }
156}
157
158// --- Floating Point Types ---
159
160// f32 (REAL)
161impl<'a> From<f32> for PostgresValue<'a> {
162    fn from(value: f32) -> Self {
163        PostgresValue::Real(value)
164    }
165}
166
167impl<'a> From<&'a f32> for PostgresValue<'a> {
168    fn from(value: &'a f32) -> Self {
169        PostgresValue::Real(*value)
170    }
171}
172
173// f64 (DOUBLE PRECISION)
174impl<'a> From<f64> for PostgresValue<'a> {
175    fn from(value: f64) -> Self {
176        PostgresValue::DoublePrecision(value)
177    }
178}
179
180impl<'a> From<&'a f64> for PostgresValue<'a> {
181    fn from(value: &'a f64) -> Self {
182        PostgresValue::DoublePrecision(*value)
183    }
184}
185
186// --- Boolean ---
187
188impl<'a> From<bool> for PostgresValue<'a> {
189    fn from(value: bool) -> Self {
190        PostgresValue::Boolean(value)
191    }
192}
193
194impl<'a> From<&'a bool> for PostgresValue<'a> {
195    fn from(value: &'a bool) -> Self {
196        PostgresValue::Boolean(*value)
197    }
198}
199
200// --- String Types ---
201
202impl<'a> From<&'a str> for PostgresValue<'a> {
203    fn from(value: &'a str) -> Self {
204        PostgresValue::Text(Cow::Borrowed(value))
205    }
206}
207
208impl<'a> From<Cow<'a, str>> for PostgresValue<'a> {
209    fn from(value: Cow<'a, str>) -> Self {
210        PostgresValue::Text(value)
211    }
212}
213
214impl<'a> From<String> for PostgresValue<'a> {
215    fn from(value: String) -> Self {
216        PostgresValue::Text(Cow::Owned(value))
217    }
218}
219
220impl<'a> From<&'a String> for PostgresValue<'a> {
221    fn from(value: &'a String) -> Self {
222        PostgresValue::Text(Cow::Borrowed(value))
223    }
224}
225
226// --- ArrayString ---
227
228#[cfg(feature = "arrayvec")]
229impl<'a, const N: usize> From<arrayvec::ArrayString<N>> for PostgresValue<'a> {
230    fn from(value: arrayvec::ArrayString<N>) -> Self {
231        PostgresValue::Text(Cow::Owned(value.to_string()))
232    }
233}
234
235#[cfg(feature = "arrayvec")]
236impl<'a, const N: usize> From<&arrayvec::ArrayString<N>> for PostgresValue<'a> {
237    fn from(value: &arrayvec::ArrayString<N>) -> Self {
238        PostgresValue::Text(Cow::Owned(value.as_str().to_owned()))
239    }
240}
241
242// --- Binary Data ---
243
244impl<'a> From<&'a [u8]> for PostgresValue<'a> {
245    fn from(value: &'a [u8]) -> Self {
246        PostgresValue::Bytea(Cow::Borrowed(value))
247    }
248}
249
250impl<'a> From<Cow<'a, [u8]>> for PostgresValue<'a> {
251    fn from(value: Cow<'a, [u8]>) -> Self {
252        PostgresValue::Bytea(value)
253    }
254}
255
256impl<'a> From<Vec<u8>> for PostgresValue<'a> {
257    fn from(value: Vec<u8>) -> Self {
258        PostgresValue::Bytea(Cow::Owned(value))
259    }
260}
261
262// --- ArrayVec<u8, N> ---
263
264#[cfg(feature = "arrayvec")]
265impl<'a, const N: usize> From<arrayvec::ArrayVec<u8, N>> for PostgresValue<'a> {
266    fn from(value: arrayvec::ArrayVec<u8, N>) -> Self {
267        PostgresValue::Bytea(Cow::Owned(value.to_vec()))
268    }
269}
270
271#[cfg(feature = "arrayvec")]
272impl<'a, const N: usize> From<&arrayvec::ArrayVec<u8, N>> for PostgresValue<'a> {
273    fn from(value: &arrayvec::ArrayVec<u8, N>) -> Self {
274        PostgresValue::Bytea(Cow::Owned(value.to_vec()))
275    }
276}
277
278// --- UUID ---
279
280#[cfg(feature = "uuid")]
281impl<'a> From<Uuid> for PostgresValue<'a> {
282    fn from(value: Uuid) -> Self {
283        PostgresValue::Uuid(value)
284    }
285}
286
287#[cfg(feature = "uuid")]
288impl<'a> From<&'a Uuid> for PostgresValue<'a> {
289    fn from(value: &'a Uuid) -> Self {
290        PostgresValue::Uuid(*value)
291    }
292}
293
294// --- JSON ---
295
296#[cfg(feature = "serde")]
297impl<'a> From<serde_json::Value> for PostgresValue<'a> {
298    fn from(value: serde_json::Value) -> Self {
299        PostgresValue::Json(value)
300    }
301}
302
303#[cfg(feature = "serde")]
304impl<'a> From<&'a serde_json::Value> for PostgresValue<'a> {
305    fn from(value: &'a serde_json::Value) -> Self {
306        PostgresValue::Json(value.clone())
307    }
308}
309
310// --- Date/Time Types ---
311
312#[cfg(feature = "chrono")]
313impl<'a> From<NaiveDate> for PostgresValue<'a> {
314    fn from(value: NaiveDate) -> Self {
315        PostgresValue::Date(value)
316    }
317}
318
319#[cfg(feature = "chrono")]
320impl<'a> From<&'a NaiveDate> for PostgresValue<'a> {
321    fn from(value: &'a NaiveDate) -> Self {
322        PostgresValue::Date(*value)
323    }
324}
325
326#[cfg(feature = "chrono")]
327impl<'a> From<NaiveTime> for PostgresValue<'a> {
328    fn from(value: NaiveTime) -> Self {
329        PostgresValue::Time(value)
330    }
331}
332
333#[cfg(feature = "chrono")]
334impl<'a> From<&'a NaiveTime> for PostgresValue<'a> {
335    fn from(value: &'a NaiveTime) -> Self {
336        PostgresValue::Time(*value)
337    }
338}
339
340#[cfg(feature = "chrono")]
341impl<'a> From<NaiveDateTime> for PostgresValue<'a> {
342    fn from(value: NaiveDateTime) -> Self {
343        PostgresValue::Timestamp(value)
344    }
345}
346
347#[cfg(feature = "chrono")]
348impl<'a> From<&'a NaiveDateTime> for PostgresValue<'a> {
349    fn from(value: &'a NaiveDateTime) -> Self {
350        PostgresValue::Timestamp(*value)
351    }
352}
353
354#[cfg(feature = "chrono")]
355impl<'a> From<DateTime<FixedOffset>> for PostgresValue<'a> {
356    fn from(value: DateTime<FixedOffset>) -> Self {
357        PostgresValue::TimestampTz(value)
358    }
359}
360
361#[cfg(feature = "chrono")]
362impl<'a> From<&'a DateTime<FixedOffset>> for PostgresValue<'a> {
363    fn from(value: &'a DateTime<FixedOffset>) -> Self {
364        PostgresValue::TimestampTz(*value)
365    }
366}
367
368#[cfg(feature = "chrono")]
369impl<'a> From<DateTime<Utc>> for PostgresValue<'a> {
370    fn from(value: DateTime<Utc>) -> Self {
371        PostgresValue::TimestampTz(value.into())
372    }
373}
374
375#[cfg(feature = "chrono")]
376impl<'a> From<&'a DateTime<Utc>> for PostgresValue<'a> {
377    fn from(value: &'a DateTime<Utc>) -> Self {
378        PostgresValue::TimestampTz((*value).into())
379    }
380}
381
382#[cfg(feature = "chrono")]
383impl<'a> From<Duration> for PostgresValue<'a> {
384    fn from(value: Duration) -> Self {
385        PostgresValue::Interval(value)
386    }
387}
388
389#[cfg(feature = "chrono")]
390impl<'a> From<&'a Duration> for PostgresValue<'a> {
391    fn from(value: &'a Duration) -> Self {
392        PostgresValue::Interval(*value)
393    }
394}
395
396// --- Network Address Types ---
397
398#[cfg(feature = "cidr")]
399impl<'a> From<IpInet> for PostgresValue<'a> {
400    fn from(value: IpInet) -> Self {
401        PostgresValue::Inet(value)
402    }
403}
404
405#[cfg(feature = "cidr")]
406impl<'a> From<&'a IpInet> for PostgresValue<'a> {
407    fn from(value: &'a IpInet) -> Self {
408        PostgresValue::Inet(*value)
409    }
410}
411
412#[cfg(feature = "cidr")]
413impl<'a> From<IpCidr> for PostgresValue<'a> {
414    fn from(value: IpCidr) -> Self {
415        PostgresValue::Cidr(value)
416    }
417}
418
419#[cfg(feature = "cidr")]
420impl<'a> From<&'a IpCidr> for PostgresValue<'a> {
421    fn from(value: &'a IpCidr) -> Self {
422        PostgresValue::Cidr(*value)
423    }
424}
425
426#[cfg(feature = "cidr")]
427impl<'a> From<[u8; 6]> for PostgresValue<'a> {
428    fn from(value: [u8; 6]) -> Self {
429        PostgresValue::MacAddr(value)
430    }
431}
432
433#[cfg(feature = "cidr")]
434impl<'a> From<&'a [u8; 6]> for PostgresValue<'a> {
435    fn from(value: &'a [u8; 6]) -> Self {
436        PostgresValue::MacAddr(*value)
437    }
438}
439
440#[cfg(feature = "cidr")]
441impl<'a> From<[u8; 8]> for PostgresValue<'a> {
442    fn from(value: [u8; 8]) -> Self {
443        PostgresValue::MacAddr8(value)
444    }
445}
446
447#[cfg(feature = "cidr")]
448impl<'a> From<&'a [u8; 8]> for PostgresValue<'a> {
449    fn from(value: &'a [u8; 8]) -> Self {
450        PostgresValue::MacAddr8(*value)
451    }
452}
453
454// --- Geometric Types ---
455
456#[cfg(feature = "geo-types")]
457impl<'a> From<Point<f64>> for PostgresValue<'a> {
458    fn from(value: Point<f64>) -> Self {
459        PostgresValue::Point(value)
460    }
461}
462
463#[cfg(feature = "geo-types")]
464impl<'a> From<&'a Point<f64>> for PostgresValue<'a> {
465    fn from(value: &'a Point<f64>) -> Self {
466        PostgresValue::Point(*value)
467    }
468}
469
470#[cfg(feature = "geo-types")]
471impl<'a> From<LineString<f64>> for PostgresValue<'a> {
472    fn from(value: LineString<f64>) -> Self {
473        PostgresValue::LineString(value)
474    }
475}
476
477#[cfg(feature = "geo-types")]
478impl<'a> From<&'a LineString<f64>> for PostgresValue<'a> {
479    fn from(value: &'a LineString<f64>) -> Self {
480        PostgresValue::LineString(value.clone())
481    }
482}
483
484#[cfg(feature = "geo-types")]
485impl<'a> From<Rect<f64>> for PostgresValue<'a> {
486    fn from(value: Rect<f64>) -> Self {
487        PostgresValue::Rect(value)
488    }
489}
490
491#[cfg(feature = "geo-types")]
492impl<'a> From<&'a Rect<f64>> for PostgresValue<'a> {
493    fn from(value: &'a Rect<f64>) -> Self {
494        PostgresValue::Rect(*value)
495    }
496}
497
498// --- Bit String Types ---
499
500#[cfg(feature = "bit-vec")]
501impl<'a> From<BitVec> for PostgresValue<'a> {
502    fn from(value: BitVec) -> Self {
503        PostgresValue::BitVec(value)
504    }
505}
506
507#[cfg(feature = "bit-vec")]
508impl<'a> From<&'a BitVec> for PostgresValue<'a> {
509    fn from(value: &'a BitVec) -> Self {
510        PostgresValue::BitVec(value.clone())
511    }
512}
513
514// --- Array Types ---
515
516impl<'a> From<Vec<PostgresValue<'a>>> for PostgresValue<'a> {
517    fn from(value: Vec<PostgresValue<'a>>) -> Self {
518        PostgresValue::Array(value)
519    }
520}
521
522impl<'a> From<&'a [PostgresValue<'a>]> for PostgresValue<'a> {
523    fn from(value: &'a [PostgresValue<'a>]) -> Self {
524        PostgresValue::Array(value.to_vec())
525    }
526}
527
528// --- Option Types ---
529impl<'a, T> From<Option<T>> for PostgresValue<'a>
530where
531    T: TryInto<PostgresValue<'a>>,
532{
533    fn from(value: Option<T>) -> Self {
534        match value {
535            Some(value) => value.try_into().unwrap_or(PostgresValue::Null),
536            None => PostgresValue::Null,
537        }
538    }
539}
540
541//------------------------------------------------------------------------------
542// TryFrom<PostgresValue> implementations
543//------------------------------------------------------------------------------
544
545// --- Integer Types ---
546
547impl<'a> TryFrom<PostgresValue<'a>> for i16 {
548    type Error = DrizzleError;
549
550    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
551        match value {
552            PostgresValue::Smallint(i) => Ok(i),
553            PostgresValue::Integer(i) => Ok(i.try_into()?),
554            PostgresValue::Bigint(i) => Ok(i.try_into()?),
555            _ => Err(DrizzleError::ConversionError(
556                format!("Cannot convert {:?} to i16", value).into(),
557            )),
558        }
559    }
560}
561
562impl<'a> TryFrom<PostgresValue<'a>> for i32 {
563    type Error = DrizzleError;
564
565    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
566        match value {
567            PostgresValue::Smallint(i) => Ok(i.into()),
568            PostgresValue::Integer(i) => Ok(i),
569            PostgresValue::Bigint(i) => Ok(i.try_into()?),
570            _ => Err(DrizzleError::ConversionError(
571                format!("Cannot convert {:?} to i32", value).into(),
572            )),
573        }
574    }
575}
576
577impl<'a> TryFrom<PostgresValue<'a>> for i64 {
578    type Error = DrizzleError;
579
580    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
581        match value {
582            PostgresValue::Smallint(i) => Ok(i.into()),
583            PostgresValue::Integer(i) => Ok(i.into()),
584            PostgresValue::Bigint(i) => Ok(i),
585            _ => Err(DrizzleError::ConversionError(
586                format!("Cannot convert {:?} to i64", value).into(),
587            )),
588        }
589    }
590}
591
592// --- Floating Point Types ---
593
594impl<'a> TryFrom<PostgresValue<'a>> for f32 {
595    type Error = DrizzleError;
596
597    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
598        match value {
599            PostgresValue::Real(f) => Ok(f),
600            PostgresValue::DoublePrecision(f) => Ok(f as f32),
601            PostgresValue::Smallint(i) => Ok(i as f32),
602            PostgresValue::Integer(i) => Ok(i as f32),
603            PostgresValue::Bigint(i) => Ok(i as f32),
604            _ => Err(DrizzleError::ConversionError(
605                format!("Cannot convert {:?} to f32", value).into(),
606            )),
607        }
608    }
609}
610
611impl<'a> TryFrom<PostgresValue<'a>> for f64 {
612    type Error = DrizzleError;
613
614    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
615        match value {
616            PostgresValue::Real(f) => Ok(f as f64),
617            PostgresValue::DoublePrecision(f) => Ok(f),
618            PostgresValue::Smallint(i) => Ok(i as f64),
619            PostgresValue::Integer(i) => Ok(i as f64),
620            PostgresValue::Bigint(i) => Ok(i as f64),
621            _ => Err(DrizzleError::ConversionError(
622                format!("Cannot convert {:?} to f64", value).into(),
623            )),
624        }
625    }
626}
627
628// --- Boolean ---
629
630impl<'a> TryFrom<PostgresValue<'a>> for bool {
631    type Error = DrizzleError;
632
633    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
634        match value {
635            PostgresValue::Boolean(b) => Ok(b),
636            _ => Err(DrizzleError::ConversionError(
637                format!("Cannot convert {:?} to bool", value).into(),
638            )),
639        }
640    }
641}
642
643// --- String Types ---
644
645impl<'a> TryFrom<PostgresValue<'a>> for String {
646    type Error = DrizzleError;
647
648    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
649        match value {
650            PostgresValue::Text(cow) => Ok(cow.into_owned()),
651            _ => Err(DrizzleError::ConversionError(
652                format!("Cannot convert {:?} to String", value).into(),
653            )),
654        }
655    }
656}
657
658// --- Binary Data ---
659
660impl<'a> TryFrom<PostgresValue<'a>> for Vec<u8> {
661    type Error = DrizzleError;
662
663    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
664        match value {
665            PostgresValue::Bytea(cow) => Ok(cow.into_owned()),
666            _ => Err(DrizzleError::ConversionError(
667                format!("Cannot convert {:?} to Vec<u8>", value).into(),
668            )),
669        }
670    }
671}
672
673impl<'a> TryFrom<&'a PostgresValue<'a>> for &'a str {
674    type Error = DrizzleError;
675
676    fn try_from(value: &'a PostgresValue<'a>) -> Result<Self, Self::Error> {
677        match value {
678            PostgresValue::Text(cow) => Ok(cow.as_ref()),
679            _ => Err(DrizzleError::ConversionError(
680                format!("Cannot convert {:?} to &str", value).into(),
681            )),
682        }
683    }
684}
685
686impl<'a> TryFrom<&'a PostgresValue<'a>> for &'a [u8] {
687    type Error = DrizzleError;
688
689    fn try_from(value: &'a PostgresValue<'a>) -> Result<Self, Self::Error> {
690        match value {
691            PostgresValue::Bytea(cow) => Ok(cow.as_ref()),
692            _ => Err(DrizzleError::ConversionError(
693                format!("Cannot convert {:?} to &[u8]", value).into(),
694            )),
695        }
696    }
697}
698
699// --- UUID ---
700
701#[cfg(feature = "uuid")]
702impl<'a> TryFrom<PostgresValue<'a>> for Uuid {
703    type Error = DrizzleError;
704
705    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
706        match value {
707            PostgresValue::Uuid(uuid) => Ok(uuid),
708            PostgresValue::Text(cow) => Uuid::parse_str(cow.as_ref()).map_err(|e| {
709                DrizzleError::ConversionError(format!("Failed to parse UUID: {}", e).into())
710            }),
711            _ => Err(DrizzleError::ConversionError(
712                format!("Cannot convert {:?} to UUID", value).into(),
713            )),
714        }
715    }
716}
717
718// --- JSON ---
719
720#[cfg(feature = "serde")]
721impl<'a> TryFrom<PostgresValue<'a>> for serde_json::Value {
722    type Error = DrizzleError;
723
724    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
725        match value {
726            PostgresValue::Json(json) => Ok(json),
727            PostgresValue::Jsonb(json) => Ok(json),
728            PostgresValue::Text(cow) => serde_json::from_str(cow.as_ref()).map_err(|e| {
729                DrizzleError::ConversionError(format!("Failed to parse JSON: {}", e).into())
730            }),
731            _ => Err(DrizzleError::ConversionError(
732                format!("Cannot convert {:?} to JSON", value).into(),
733            )),
734        }
735    }
736}
737
738// --- Date/Time TryFrom implementations ---
739
740#[cfg(feature = "chrono")]
741impl<'a> TryFrom<PostgresValue<'a>> for NaiveDate {
742    type Error = DrizzleError;
743
744    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
745        match value {
746            PostgresValue::Date(date) => Ok(date),
747            PostgresValue::Timestamp(ts) => Ok(ts.date()),
748            PostgresValue::TimestampTz(ts) => Ok(ts.date_naive()),
749            _ => Err(DrizzleError::ConversionError(
750                format!("Cannot convert {:?} to NaiveDate", value).into(),
751            )),
752        }
753    }
754}
755
756#[cfg(feature = "chrono")]
757impl<'a> TryFrom<PostgresValue<'a>> for NaiveTime {
758    type Error = DrizzleError;
759
760    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
761        match value {
762            PostgresValue::Time(time) => Ok(time),
763            PostgresValue::Timestamp(ts) => Ok(ts.time()),
764            PostgresValue::TimestampTz(ts) => Ok(ts.time()),
765            _ => Err(DrizzleError::ConversionError(
766                format!("Cannot convert {:?} to NaiveTime", value).into(),
767            )),
768        }
769    }
770}
771
772#[cfg(feature = "chrono")]
773impl<'a> TryFrom<PostgresValue<'a>> for NaiveDateTime {
774    type Error = DrizzleError;
775
776    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
777        match value {
778            PostgresValue::Timestamp(ts) => Ok(ts),
779            PostgresValue::TimestampTz(ts) => Ok(ts.naive_utc()),
780            _ => Err(DrizzleError::ConversionError(
781                format!("Cannot convert {:?} to NaiveDateTime", value).into(),
782            )),
783        }
784    }
785}
786
787#[cfg(feature = "chrono")]
788impl<'a> TryFrom<PostgresValue<'a>> for DateTime<FixedOffset> {
789    type Error = DrizzleError;
790
791    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
792        match value {
793            PostgresValue::TimestampTz(ts) => Ok(ts),
794            _ => Err(DrizzleError::ConversionError(
795                format!("Cannot convert {:?} to DateTime<FixedOffset>", value).into(),
796            )),
797        }
798    }
799}
800
801#[cfg(feature = "chrono")]
802impl<'a> TryFrom<PostgresValue<'a>> for DateTime<Utc> {
803    type Error = DrizzleError;
804
805    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
806        match value {
807            PostgresValue::TimestampTz(ts) => Ok(ts.with_timezone(&Utc)),
808            _ => Err(DrizzleError::ConversionError(
809                format!("Cannot convert {:?} to DateTime<Utc>", value).into(),
810            )),
811        }
812    }
813}
814
815#[cfg(feature = "chrono")]
816impl<'a> TryFrom<PostgresValue<'a>> for Duration {
817    type Error = DrizzleError;
818
819    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
820        match value {
821            PostgresValue::Interval(duration) => Ok(duration),
822            _ => Err(DrizzleError::ConversionError(
823                format!("Cannot convert {:?} to Duration", value).into(),
824            )),
825        }
826    }
827}
828
829// --- Network Address TryFrom implementations ---
830
831#[cfg(feature = "cidr")]
832impl<'a> TryFrom<PostgresValue<'a>> for IpInet {
833    type Error = DrizzleError;
834
835    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
836        match value {
837            PostgresValue::Inet(net) => Ok(net),
838            _ => Err(DrizzleError::ConversionError(
839                format!("Cannot convert {:?} to IpInet", value).into(),
840            )),
841        }
842    }
843}
844
845#[cfg(feature = "cidr")]
846impl<'a> TryFrom<PostgresValue<'a>> for IpCidr {
847    type Error = DrizzleError;
848
849    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
850        match value {
851            PostgresValue::Cidr(net) => Ok(net),
852            _ => Err(DrizzleError::ConversionError(
853                format!("Cannot convert {:?} to IpCidr", value).into(),
854            )),
855        }
856    }
857}
858
859#[cfg(feature = "cidr")]
860impl<'a> TryFrom<PostgresValue<'a>> for [u8; 6] {
861    type Error = DrizzleError;
862
863    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
864        match value {
865            PostgresValue::MacAddr(mac) => Ok(mac),
866            _ => Err(DrizzleError::ConversionError(
867                format!("Cannot convert {:?} to [u8; 6]", value).into(),
868            )),
869        }
870    }
871}
872
873#[cfg(feature = "cidr")]
874impl<'a> TryFrom<PostgresValue<'a>> for [u8; 8] {
875    type Error = DrizzleError;
876
877    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
878        match value {
879            PostgresValue::MacAddr8(mac) => Ok(mac),
880            _ => Err(DrizzleError::ConversionError(
881                format!("Cannot convert {:?} to [u8; 8]", value).into(),
882            )),
883        }
884    }
885}
886
887// --- Geometric TryFrom implementations ---
888
889#[cfg(feature = "geo-types")]
890impl<'a> TryFrom<PostgresValue<'a>> for Point<f64> {
891    type Error = DrizzleError;
892
893    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
894        match value {
895            PostgresValue::Point(point) => Ok(point),
896            _ => Err(DrizzleError::ConversionError(
897                format!("Cannot convert {:?} to Point", value).into(),
898            )),
899        }
900    }
901}
902
903#[cfg(feature = "geo-types")]
904impl<'a> TryFrom<PostgresValue<'a>> for LineString<f64> {
905    type Error = DrizzleError;
906
907    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
908        match value {
909            PostgresValue::LineString(line) => Ok(line),
910            _ => Err(DrizzleError::ConversionError(
911                format!("Cannot convert {:?} to LineString", value).into(),
912            )),
913        }
914    }
915}
916
917#[cfg(feature = "geo-types")]
918impl<'a> TryFrom<PostgresValue<'a>> for Rect<f64> {
919    type Error = DrizzleError;
920
921    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
922        match value {
923            PostgresValue::Rect(rect) => Ok(rect),
924            _ => Err(DrizzleError::ConversionError(
925                format!("Cannot convert {:?} to Rect", value).into(),
926            )),
927        }
928    }
929}
930
931// --- Bit String TryFrom implementations ---
932
933#[cfg(feature = "bit-vec")]
934impl<'a> TryFrom<PostgresValue<'a>> for BitVec {
935    type Error = DrizzleError;
936
937    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
938        match value {
939            PostgresValue::BitVec(bv) => Ok(bv),
940            _ => Err(DrizzleError::ConversionError(
941                format!("Cannot convert {:?} to BitVec", value).into(),
942            )),
943        }
944    }
945}
946
947// --- ArrayVec TryFrom implementations ---
948
949#[cfg(feature = "arrayvec")]
950impl<'a, const N: usize> TryFrom<PostgresValue<'a>> for arrayvec::ArrayString<N> {
951    type Error = DrizzleError;
952
953    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
954        match value {
955            PostgresValue::Text(cow_str) => {
956                arrayvec::ArrayString::from(cow_str.as_ref()).map_err(|_| {
957                    DrizzleError::ConversionError(
958                        format!(
959                            "Text length {} exceeds ArrayString capacity {}",
960                            cow_str.len(),
961                            N
962                        )
963                        .into(),
964                    )
965                })
966            }
967            _ => Err(DrizzleError::ConversionError(
968                format!("Cannot convert {:?} to ArrayString", value).into(),
969            )),
970        }
971    }
972}
973
974#[cfg(feature = "arrayvec")]
975impl<'a, const N: usize> TryFrom<PostgresValue<'a>> for arrayvec::ArrayVec<u8, N> {
976    type Error = DrizzleError;
977
978    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
979        match value {
980            PostgresValue::Bytea(cow_bytes) => arrayvec::ArrayVec::try_from(cow_bytes.as_ref())
981                .map_err(|_| {
982                    DrizzleError::ConversionError(
983                        format!(
984                            "Bytea length {} exceeds ArrayVec capacity {}",
985                            cow_bytes.len(),
986                            N
987                        )
988                        .into(),
989                    )
990                }),
991            _ => Err(DrizzleError::ConversionError(
992                format!("Cannot convert {:?} to ArrayVec<u8>", value).into(),
993            )),
994        }
995    }
996}
997
998// --- Array TryFrom implementations ---
999
1000impl<'a> TryFrom<PostgresValue<'a>> for Vec<PostgresValue<'a>> {
1001    type Error = DrizzleError;
1002
1003    fn try_from(value: PostgresValue<'a>) -> Result<Self, Self::Error> {
1004        match value {
1005            PostgresValue::Array(arr) => Ok(arr),
1006            _ => Err(DrizzleError::ConversionError(
1007                format!("Cannot convert {:?} to Vec<PostgresValue>", value).into(),
1008            )),
1009        }
1010    }
1011}
1012
1013impl<'a> TryFrom<&'a PostgresValue<'a>> for &'a [PostgresValue<'a>] {
1014    type Error = DrizzleError;
1015
1016    fn try_from(value: &'a PostgresValue<'a>) -> Result<Self, Self::Error> {
1017        match value {
1018            PostgresValue::Array(arr) => Ok(arr),
1019            _ => Err(DrizzleError::ConversionError(
1020                format!("Cannot convert {:?} to &[PostgresValue]", value).into(),
1021            )),
1022        }
1023    }
1024}