Skip to main content

drizzle_postgres/traits/
value.rs

1//! Value conversion traits for `PostgreSQL` types
2//!
3//! This module provides the `FromPostgresValue` trait for converting `PostgreSQL` values
4//! to Rust types, and row capability traits for unified access across drivers.
5//!
6//! This pattern mirrors the `SQLite` implementation to provide driver-agnostic
7//! row conversions for postgres, tokio-postgres, and potentially other drivers.
8
9use crate::prelude::*;
10use crate::values::{OwnedPostgresValue, PostgresValue};
11use drizzle_core::conv::checked_float_to_int;
12use drizzle_core::error::DrizzleError;
13
14/// Trait for types that can be converted from `PostgreSQL` values.
15///
16/// `PostgreSQL` has many types, but this trait focuses on the core conversions:
17/// - Integers (i16, i32, i64)
18/// - Floats (f32, f64)
19/// - Text (String, &str)
20/// - Binary (`Vec<u8>`, `&[u8]`)
21/// - Boolean
22/// - NULL handling
23///
24/// # Implementation Notes
25///
26/// - Implement the methods that make sense for your type
27/// - Return `Err` for unsupported conversions
28/// - `PostgresEnum` derive automatically implements this trait
29pub trait FromPostgresValue: Sized {
30    /// Convert from a boolean value
31    ///
32    /// # Errors
33    ///
34    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
35    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError>;
36
37    /// Convert from a 16-bit integer value
38    ///
39    /// # Errors
40    ///
41    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
42    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError>;
43
44    /// Convert from a 32-bit integer value
45    ///
46    /// # Errors
47    ///
48    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
49    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError>;
50
51    /// Convert from a 64-bit integer value
52    ///
53    /// # Errors
54    ///
55    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
56    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError>;
57
58    /// Convert from a 32-bit float value
59    ///
60    /// # Errors
61    ///
62    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
63    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError>;
64
65    /// Convert from a 64-bit float value
66    ///
67    /// # Errors
68    ///
69    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
70    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError>;
71
72    /// Convert from a text/string value
73    ///
74    /// # Errors
75    ///
76    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
77    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError>;
78
79    /// Convert from a binary/bytea value
80    ///
81    /// # Errors
82    ///
83    /// Returns [`DrizzleError::ConversionError`] if the value cannot be represented as the target type.
84    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError>;
85
86    /// Convert from a NULL value (default returns error)
87    ///
88    /// # Errors
89    ///
90    /// Returns [`DrizzleError::ConversionError`] unless the implementor treats NULL as a valid value.
91    fn from_postgres_null() -> Result<Self, DrizzleError> {
92        Err(DrizzleError::ConversionError(
93            "unexpected NULL value".into(),
94        ))
95    }
96
97    /// Convert from a UUID value
98    ///
99    /// # Errors
100    ///
101    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a UUID.
102    #[cfg(feature = "uuid")]
103    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
104        Err(DrizzleError::ConversionError(
105            format!("cannot convert UUID {value} to target type").into(),
106        ))
107    }
108
109    /// Convert from a JSON value
110    ///
111    /// # Errors
112    ///
113    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a JSON value.
114    #[cfg(feature = "serde")]
115    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
116        Err(DrizzleError::ConversionError(
117            format!("cannot convert JSON {value} to target type").into(),
118        ))
119    }
120
121    /// Convert from a JSONB value
122    ///
123    /// # Errors
124    ///
125    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a JSONB value.
126    #[cfg(feature = "serde")]
127    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
128        Err(DrizzleError::ConversionError(
129            format!("cannot convert JSONB {value} to target type").into(),
130        ))
131    }
132
133    /// Convert from an ARRAY value
134    ///
135    /// # Errors
136    ///
137    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an ARRAY value.
138    fn from_postgres_array(_value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
139        Err(DrizzleError::ConversionError(
140            "cannot convert ARRAY to target type".into(),
141        ))
142    }
143
144    /// Convert from a DATE value
145    ///
146    /// # Errors
147    ///
148    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
149    #[cfg(feature = "chrono")]
150    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
151        Err(DrizzleError::ConversionError(
152            format!("cannot convert DATE {value} to target type").into(),
153        ))
154    }
155
156    /// Convert from a TIME value
157    ///
158    /// # Errors
159    ///
160    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
161    #[cfg(feature = "chrono")]
162    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
163        Err(DrizzleError::ConversionError(
164            format!("cannot convert TIME {value} to target type").into(),
165        ))
166    }
167
168    /// Convert from a TIMESTAMP value
169    ///
170    /// # Errors
171    ///
172    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
173    #[cfg(feature = "chrono")]
174    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
175        Err(DrizzleError::ConversionError(
176            format!("cannot convert TIMESTAMP {value} to target type").into(),
177        ))
178    }
179
180    /// Convert from a TIMESTAMPTZ value
181    ///
182    /// # Errors
183    ///
184    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
185    #[cfg(feature = "chrono")]
186    fn from_postgres_timestamptz(
187        value: chrono::DateTime<chrono::FixedOffset>,
188    ) -> Result<Self, DrizzleError> {
189        Err(DrizzleError::ConversionError(
190            format!("cannot convert TIMESTAMPTZ {value} to target type").into(),
191        ))
192    }
193
194    /// Convert from an INTERVAL value
195    ///
196    /// # Errors
197    ///
198    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INTERVAL.
199    #[cfg(feature = "chrono")]
200    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
201        Err(DrizzleError::ConversionError(
202            format!("cannot convert INTERVAL {value} to target type").into(),
203        ))
204    }
205
206    /// Convert from a DATE value (time crate)
207    ///
208    /// # Errors
209    ///
210    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
211    #[cfg(feature = "time")]
212    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
213        Err(DrizzleError::ConversionError(
214            format!("cannot convert DATE (time) {value:?} to target type").into(),
215        ))
216    }
217
218    /// Convert from a TIME value (time crate)
219    ///
220    /// # Errors
221    ///
222    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
223    #[cfg(feature = "time")]
224    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
225        Err(DrizzleError::ConversionError(
226            format!("cannot convert TIME (time) {value:?} to target type").into(),
227        ))
228    }
229
230    /// Convert from a TIMESTAMP value (time crate)
231    ///
232    /// # Errors
233    ///
234    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
235    #[cfg(feature = "time")]
236    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
237        Err(DrizzleError::ConversionError(
238            format!("cannot convert TIMESTAMP (time) {value:?} to target type").into(),
239        ))
240    }
241
242    /// Convert from a TIMESTAMPTZ value (time crate)
243    ///
244    /// # Errors
245    ///
246    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
247    #[cfg(feature = "time")]
248    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
249        Err(DrizzleError::ConversionError(
250            format!("cannot convert TIMESTAMPTZ (time) {value:?} to target type").into(),
251        ))
252    }
253
254    /// Convert from an INTERVAL value (time crate)
255    ///
256    /// # Errors
257    ///
258    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INTERVAL.
259    #[cfg(feature = "time")]
260    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
261        Err(DrizzleError::ConversionError(
262            format!("cannot convert INTERVAL (time) {value:?} to target type").into(),
263        ))
264    }
265
266    /// Convert from a DATE value (jiff)
267    ///
268    /// # Errors
269    ///
270    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a DATE.
271    #[cfg(feature = "jiff")]
272    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
273        Err(DrizzleError::ConversionError(
274            format!("cannot convert DATE (jiff) {value:?} to target type").into(),
275        ))
276    }
277
278    /// Convert from a TIME value (jiff)
279    ///
280    /// # Errors
281    ///
282    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIME.
283    #[cfg(feature = "jiff")]
284    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
285        Err(DrizzleError::ConversionError(
286            format!("cannot convert TIME (jiff) {value:?} to target type").into(),
287        ))
288    }
289
290    /// Convert from a TIMESTAMP value (jiff)
291    ///
292    /// # Errors
293    ///
294    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMP.
295    #[cfg(feature = "jiff")]
296    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
297        Err(DrizzleError::ConversionError(
298            format!("cannot convert TIMESTAMP (jiff) {value:?} to target type").into(),
299        ))
300    }
301
302    /// Convert from a TIMESTAMPTZ value (jiff)
303    ///
304    /// # Errors
305    ///
306    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a TIMESTAMPTZ.
307    #[cfg(feature = "jiff")]
308    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
309        Err(DrizzleError::ConversionError(
310            format!("cannot convert TIMESTAMPTZ (jiff) {value:?} to target type").into(),
311        ))
312    }
313
314    /// Convert from an INET value
315    ///
316    /// # Errors
317    ///
318    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an INET address.
319    #[cfg(feature = "cidr")]
320    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
321        Err(DrizzleError::ConversionError(
322            format!("cannot convert INET {value} to target type").into(),
323        ))
324    }
325
326    /// Convert from a CIDR value
327    ///
328    /// # Errors
329    ///
330    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a CIDR network.
331    #[cfg(feature = "cidr")]
332    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
333        Err(DrizzleError::ConversionError(
334            format!("cannot convert CIDR {value} to target type").into(),
335        ))
336    }
337
338    /// Convert from a MACADDR value
339    ///
340    /// # Errors
341    ///
342    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a MAC address.
343    #[cfg(feature = "cidr")]
344    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
345        Err(DrizzleError::ConversionError(
346            format!("cannot convert MACADDR {value:?} to target type").into(),
347        ))
348    }
349
350    /// Convert from a MACADDR8 value
351    ///
352    /// # Errors
353    ///
354    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent an 8-byte MAC address.
355    #[cfg(feature = "cidr")]
356    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
357        Err(DrizzleError::ConversionError(
358            format!("cannot convert MACADDR8 {value:?} to target type").into(),
359        ))
360    }
361
362    /// Convert from a POINT value
363    ///
364    /// # Errors
365    ///
366    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a POINT.
367    #[cfg(feature = "geo-types")]
368    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
369        Err(DrizzleError::ConversionError(
370            format!("cannot convert POINT {value:?} to target type").into(),
371        ))
372    }
373
374    /// Convert from a PATH value
375    ///
376    /// # Errors
377    ///
378    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a PATH.
379    #[cfg(feature = "geo-types")]
380    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
381        Err(DrizzleError::ConversionError(
382            format!("cannot convert PATH {value:?} to target type").into(),
383        ))
384    }
385
386    /// Convert from a BOX value
387    ///
388    /// # Errors
389    ///
390    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a BOX.
391    #[cfg(feature = "geo-types")]
392    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
393        Err(DrizzleError::ConversionError(
394            format!("cannot convert BOX {value:?} to target type").into(),
395        ))
396    }
397
398    /// Convert from a BIT/VARBIT value
399    ///
400    /// # Errors
401    ///
402    /// Returns [`DrizzleError::ConversionError`] if the target type cannot represent a bit vector.
403    #[cfg(feature = "bit-vec")]
404    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
405        Err(DrizzleError::ConversionError(
406            format!("cannot convert BITVEC {value:?} to target type").into(),
407        ))
408    }
409}
410
411/// Row capability for index-based extraction.
412pub trait DrizzleRowByIndex {
413    /// Get a column value by index
414    ///
415    /// # Errors
416    ///
417    /// Returns [`DrizzleError`] if the column is out of bounds, the value is NULL for a non-nullable target,
418    /// or the stored value cannot be converted into `T`.
419    fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError>;
420}
421
422/// Row capability for name-based extraction.
423pub trait DrizzleRowByName: DrizzleRowByIndex {
424    /// Get a column value by name
425    ///
426    /// # Errors
427    ///
428    /// Returns [`DrizzleError`] if the column name is unknown, the value is NULL for a non-nullable target,
429    /// or the stored value cannot be converted into `T`.
430    fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError>;
431}
432
433// =============================================================================
434// Primitive implementations
435// =============================================================================
436
437impl FromPostgresValue for bool {
438    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
439        Ok(value)
440    }
441
442    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
443        Ok(value != 0)
444    }
445
446    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
447        Ok(value != 0)
448    }
449
450    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
451        Ok(value != 0)
452    }
453
454    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
455        Err(DrizzleError::ConversionError(
456            "cannot convert f32 to bool".into(),
457        ))
458    }
459
460    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
461        Err(DrizzleError::ConversionError(
462            "cannot convert f64 to bool".into(),
463        ))
464    }
465
466    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
467        match value.to_lowercase().as_str() {
468            "true" | "t" | "1" | "yes" | "on" => Ok(true),
469            "false" | "f" | "0" | "no" | "off" => Ok(false),
470            _ => Err(DrizzleError::ConversionError(
471                format!("cannot parse '{value}' as bool").into(),
472            )),
473        }
474    }
475
476    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
477        Err(DrizzleError::ConversionError(
478            "cannot convert bytes to bool".into(),
479        ))
480    }
481}
482
483/// Macro to implement `FromPostgresValue` for integer types
484macro_rules! impl_from_postgres_value_int {
485    ($($ty:ty),+ $(,)?) => {
486        $(
487            impl FromPostgresValue for $ty {
488                fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
489                    Ok(if value { 1 } else { 0 })
490                }
491
492                fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
493                    value.try_into().map_err(|e| {
494                        DrizzleError::ConversionError(
495                            format!("i16 {} out of range for {}: {}", value, stringify!($ty), e).into(),
496                        )
497                    })
498                }
499
500                fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
501                    value.try_into().map_err(|e| {
502                        DrizzleError::ConversionError(
503                            format!("i32 {} out of range for {}: {}", value, stringify!($ty), e).into(),
504                        )
505                    })
506                }
507
508                fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
509                    value.try_into().map_err(|e| {
510                        DrizzleError::ConversionError(
511                            format!("i64 {} out of range for {}: {}", value, stringify!($ty), e).into(),
512                        )
513                    })
514                }
515
516                fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
517                    checked_float_to_int(f64::from(value), stringify!($ty))
518                }
519
520                fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
521                    checked_float_to_int(value, stringify!($ty))
522                }
523
524                fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
525                    value.parse().map_err(|e| {
526                        DrizzleError::ConversionError(
527                            format!("cannot parse '{}' as {}: {}", value, stringify!($ty), e).into()
528                        )
529                    })
530                }
531
532                fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
533                    Err(DrizzleError::ConversionError(
534                        concat!("cannot convert bytes to ", stringify!($ty)).into()
535                    ))
536                }
537            }
538        )+
539    };
540}
541
542// Special case for i16 - no conversion needed
543impl FromPostgresValue for i16 {
544    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
545        Ok(Self::from(value))
546    }
547
548    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
549        Ok(value)
550    }
551
552    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
553        value.try_into().map_err(|e| {
554            DrizzleError::ConversionError(format!("i32 {value} out of range for i16: {e}").into())
555        })
556    }
557
558    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
559        value.try_into().map_err(|e| {
560            DrizzleError::ConversionError(format!("i64 {value} out of range for i16: {e}").into())
561        })
562    }
563
564    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
565        checked_float_to_int(f64::from(value), "i16")
566    }
567
568    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
569        checked_float_to_int(value, "i16")
570    }
571
572    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
573        value.parse().map_err(|e| {
574            DrizzleError::ConversionError(format!("cannot parse '{value}' as i16: {e}").into())
575        })
576    }
577
578    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
579        Err(DrizzleError::ConversionError(
580            "cannot convert bytes to i16".into(),
581        ))
582    }
583}
584
585// Special case for i32 - no conversion needed
586impl FromPostgresValue for i32 {
587    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
588        Ok(Self::from(value))
589    }
590
591    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
592        Ok(Self::from(value))
593    }
594
595    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
596        Ok(value)
597    }
598
599    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
600        value.try_into().map_err(|e| {
601            DrizzleError::ConversionError(format!("i64 {value} out of range for i32: {e}").into())
602        })
603    }
604
605    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
606        checked_float_to_int(f64::from(value), "i32")
607    }
608
609    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
610        checked_float_to_int(value, "i32")
611    }
612
613    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
614        value.parse().map_err(|e| {
615            DrizzleError::ConversionError(format!("cannot parse '{value}' as i32: {e}").into())
616        })
617    }
618
619    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
620        Err(DrizzleError::ConversionError(
621            "cannot convert bytes to i32".into(),
622        ))
623    }
624}
625
626// Special case for i64 - no conversion needed
627impl FromPostgresValue for i64 {
628    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
629        Ok(Self::from(value))
630    }
631
632    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
633        Ok(Self::from(value))
634    }
635
636    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
637        Ok(Self::from(value))
638    }
639
640    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
641        Ok(value)
642    }
643
644    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
645        checked_float_to_int(f64::from(value), "i64")
646    }
647
648    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
649        checked_float_to_int(value, "i64")
650    }
651
652    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
653        value.parse().map_err(|e| {
654            DrizzleError::ConversionError(format!("cannot parse '{value}' as i64: {e}").into())
655        })
656    }
657
658    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
659        Err(DrizzleError::ConversionError(
660            "cannot convert bytes to i64".into(),
661        ))
662    }
663}
664
665// Other integer types that need conversion
666impl_from_postgres_value_int!(i8, u8, u16, u32, u64, isize, usize);
667
668/// Parses an integer via its decimal string form into a float.
669///
670/// This avoids the `cast_precision_loss` lint for `i32 as f32` / `i64 as f32` /
671/// `i64 as f64` while preserving round-to-nearest semantics.
672#[inline]
673fn int_to_float<I: core::fmt::Display, F: core::str::FromStr>(value: I) -> Result<F, DrizzleError>
674where
675    <F as core::str::FromStr>::Err: core::fmt::Display,
676{
677    let s = format!("{value}");
678    s.parse::<F>().map_err(|e| {
679        DrizzleError::ConversionError(format!("cannot convert '{s}' to float: {e}").into())
680    })
681}
682
683impl FromPostgresValue for f64 {
684    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
685        Ok(if value { 1.0 } else { 0.0 })
686    }
687
688    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
689        Ok(Self::from(value))
690    }
691
692    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
693        Ok(Self::from(value))
694    }
695
696    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
697        // Decimal round-trip preserves round-to-nearest without an `as` cast.
698        int_to_float::<_, Self>(value)
699    }
700
701    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
702        Ok(Self::from(value))
703    }
704
705    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
706        Ok(value)
707    }
708
709    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
710        value.parse().map_err(|e: core::num::ParseFloatError| {
711            DrizzleError::ConversionError(format!("cannot parse '{value}' as f64: {e}").into())
712        })
713    }
714
715    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
716        Err(DrizzleError::ConversionError(
717            "cannot convert bytes to f64".into(),
718        ))
719    }
720}
721
722impl FromPostgresValue for f32 {
723    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
724        Ok(if value { 1.0 } else { 0.0 })
725    }
726
727    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
728        Ok(Self::from(value))
729    }
730
731    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
732        int_to_float::<_, Self>(value)
733    }
734
735    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
736        int_to_float::<_, Self>(value)
737    }
738
739    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
740        Ok(value)
741    }
742
743    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
744        // Round via decimal round-trip instead of the lossy `as` cast.
745        let s = format!("{value}");
746        s.parse::<Self>().map_err(|e| {
747            DrizzleError::ConversionError(format!("cannot convert '{s}' to f32: {e}").into())
748        })
749    }
750
751    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
752        value.parse().map_err(|e: core::num::ParseFloatError| {
753            DrizzleError::ConversionError(format!("cannot parse '{value}' as f32: {e}").into())
754        })
755    }
756
757    fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
758        Err(DrizzleError::ConversionError(
759            "cannot convert bytes to f32".into(),
760        ))
761    }
762}
763
764impl FromPostgresValue for String {
765    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
766        Ok(value.to_string())
767    }
768
769    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
770        Ok(value.to_string())
771    }
772
773    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
774        Ok(value.to_string())
775    }
776
777    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
778        Ok(value.to_string())
779    }
780
781    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
782        Ok(value.to_string())
783    }
784
785    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
786        Ok(value.to_string())
787    }
788
789    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
790        Ok(value.to_string())
791    }
792
793    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
794        Self::from_utf8(value.to_vec()).map_err(|e| {
795            DrizzleError::ConversionError(format!("invalid UTF-8 in bytes: {e}").into())
796        })
797    }
798}
799
800impl FromPostgresValue for Box<String> {
801    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
802        String::from_postgres_bool(value).map(Self::new)
803    }
804
805    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
806        String::from_postgres_i16(value).map(Self::new)
807    }
808
809    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
810        String::from_postgres_i32(value).map(Self::new)
811    }
812
813    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
814        String::from_postgres_i64(value).map(Self::new)
815    }
816
817    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
818        String::from_postgres_f32(value).map(Self::new)
819    }
820
821    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
822        String::from_postgres_f64(value).map(Self::new)
823    }
824
825    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
826        String::from_postgres_text(value).map(Self::new)
827    }
828
829    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
830        String::from_postgres_bytes(value).map(Self::new)
831    }
832}
833
834impl FromPostgresValue for Rc<String> {
835    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
836        String::from_postgres_bool(value).map(Self::new)
837    }
838
839    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
840        String::from_postgres_i16(value).map(Self::new)
841    }
842
843    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
844        String::from_postgres_i32(value).map(Self::new)
845    }
846
847    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
848        String::from_postgres_i64(value).map(Self::new)
849    }
850
851    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
852        String::from_postgres_f32(value).map(Self::new)
853    }
854
855    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
856        String::from_postgres_f64(value).map(Self::new)
857    }
858
859    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
860        String::from_postgres_text(value).map(Self::new)
861    }
862
863    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
864        String::from_postgres_bytes(value).map(Self::new)
865    }
866}
867
868impl FromPostgresValue for Arc<String> {
869    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
870        String::from_postgres_bool(value).map(Self::new)
871    }
872
873    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
874        String::from_postgres_i16(value).map(Self::new)
875    }
876
877    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
878        String::from_postgres_i32(value).map(Self::new)
879    }
880
881    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
882        String::from_postgres_i64(value).map(Self::new)
883    }
884
885    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
886        String::from_postgres_f32(value).map(Self::new)
887    }
888
889    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
890        String::from_postgres_f64(value).map(Self::new)
891    }
892
893    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
894        String::from_postgres_text(value).map(Self::new)
895    }
896
897    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
898        String::from_postgres_bytes(value).map(Self::new)
899    }
900}
901
902impl FromPostgresValue for Box<str> {
903    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
904        String::from_postgres_bool(value).map(String::into_boxed_str)
905    }
906
907    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
908        String::from_postgres_i16(value).map(String::into_boxed_str)
909    }
910
911    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
912        String::from_postgres_i32(value).map(String::into_boxed_str)
913    }
914
915    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
916        String::from_postgres_i64(value).map(String::into_boxed_str)
917    }
918
919    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
920        String::from_postgres_f32(value).map(String::into_boxed_str)
921    }
922
923    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
924        String::from_postgres_f64(value).map(String::into_boxed_str)
925    }
926
927    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
928        String::from_postgres_text(value).map(String::into_boxed_str)
929    }
930
931    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
932        String::from_postgres_bytes(value).map(String::into_boxed_str)
933    }
934}
935
936impl FromPostgresValue for Rc<str> {
937    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
938        String::from_postgres_bool(value).map(Self::from)
939    }
940
941    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
942        String::from_postgres_i16(value).map(Self::from)
943    }
944
945    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
946        String::from_postgres_i32(value).map(Self::from)
947    }
948
949    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
950        String::from_postgres_i64(value).map(Self::from)
951    }
952
953    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
954        String::from_postgres_f32(value).map(Self::from)
955    }
956
957    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
958        String::from_postgres_f64(value).map(Self::from)
959    }
960
961    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
962        String::from_postgres_text(value).map(Self::from)
963    }
964
965    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
966        String::from_postgres_bytes(value).map(Self::from)
967    }
968}
969
970impl FromPostgresValue for Arc<str> {
971    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
972        String::from_postgres_bool(value).map(Self::from)
973    }
974
975    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
976        String::from_postgres_i16(value).map(Self::from)
977    }
978
979    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
980        String::from_postgres_i32(value).map(Self::from)
981    }
982
983    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
984        String::from_postgres_i64(value).map(Self::from)
985    }
986
987    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
988        String::from_postgres_f32(value).map(Self::from)
989    }
990
991    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
992        String::from_postgres_f64(value).map(Self::from)
993    }
994
995    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
996        String::from_postgres_text(value).map(Self::from)
997    }
998
999    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1000        String::from_postgres_bytes(value).map(Self::from)
1001    }
1002}
1003
1004impl FromPostgresValue for Vec<u8> {
1005    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
1006        Err(DrizzleError::ConversionError(
1007            "cannot convert bool to Vec<u8>".into(),
1008        ))
1009    }
1010
1011    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1012        Ok(value.to_le_bytes().to_vec())
1013    }
1014
1015    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1016        Ok(value.to_le_bytes().to_vec())
1017    }
1018
1019    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1020        Ok(value.to_le_bytes().to_vec())
1021    }
1022
1023    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1024        Ok(value.to_le_bytes().to_vec())
1025    }
1026
1027    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1028        Ok(value.to_le_bytes().to_vec())
1029    }
1030
1031    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1032        Ok(value.as_bytes().to_vec())
1033    }
1034
1035    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1036        Ok(value.to_vec())
1037    }
1038}
1039
1040impl FromPostgresValue for Box<Vec<u8>> {
1041    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1042        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1043    }
1044
1045    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1046        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1047    }
1048
1049    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1050        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1051    }
1052
1053    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1054        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1055    }
1056
1057    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1058        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1059    }
1060
1061    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1062        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1063    }
1064
1065    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1066        Vec::<u8>::from_postgres_text(value).map(Self::new)
1067    }
1068
1069    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1070        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1071    }
1072}
1073
1074impl FromPostgresValue for Rc<Vec<u8>> {
1075    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1076        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1077    }
1078
1079    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1080        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1081    }
1082
1083    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1084        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1085    }
1086
1087    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1088        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1089    }
1090
1091    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1092        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1093    }
1094
1095    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1096        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1097    }
1098
1099    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1100        Vec::<u8>::from_postgres_text(value).map(Self::new)
1101    }
1102
1103    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1104        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1105    }
1106}
1107
1108impl FromPostgresValue for Arc<Vec<u8>> {
1109    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1110        Vec::<u8>::from_postgres_bool(value).map(Self::new)
1111    }
1112
1113    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1114        Vec::<u8>::from_postgres_i16(value).map(Self::new)
1115    }
1116
1117    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1118        Vec::<u8>::from_postgres_i32(value).map(Self::new)
1119    }
1120
1121    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1122        Vec::<u8>::from_postgres_i64(value).map(Self::new)
1123    }
1124
1125    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1126        Vec::<u8>::from_postgres_f32(value).map(Self::new)
1127    }
1128
1129    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1130        Vec::<u8>::from_postgres_f64(value).map(Self::new)
1131    }
1132
1133    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1134        Vec::<u8>::from_postgres_text(value).map(Self::new)
1135    }
1136
1137    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1138        Vec::<u8>::from_postgres_bytes(value).map(Self::new)
1139    }
1140}
1141
1142// Option<T> implementation - handles NULL values
1143impl<T: FromPostgresValue> FromPostgresValue for Option<T> {
1144    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
1145        T::from_postgres_bool(value).map(Some)
1146    }
1147
1148    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
1149        T::from_postgres_i16(value).map(Some)
1150    }
1151
1152    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
1153        T::from_postgres_i32(value).map(Some)
1154    }
1155
1156    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
1157        T::from_postgres_i64(value).map(Some)
1158    }
1159
1160    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
1161        T::from_postgres_f32(value).map(Some)
1162    }
1163
1164    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
1165        T::from_postgres_f64(value).map(Some)
1166    }
1167
1168    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
1169        T::from_postgres_text(value).map(Some)
1170    }
1171
1172    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
1173        T::from_postgres_bytes(value).map(Some)
1174    }
1175
1176    #[cfg(feature = "uuid")]
1177    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
1178        T::from_postgres_uuid(value).map(Some)
1179    }
1180
1181    #[cfg(feature = "serde")]
1182    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
1183        T::from_postgres_json(value).map(Some)
1184    }
1185
1186    #[cfg(feature = "serde")]
1187    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
1188        T::from_postgres_jsonb(value).map(Some)
1189    }
1190
1191    #[cfg(feature = "chrono")]
1192    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
1193        T::from_postgres_date(value).map(Some)
1194    }
1195
1196    #[cfg(feature = "chrono")]
1197    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
1198        T::from_postgres_time(value).map(Some)
1199    }
1200
1201    #[cfg(feature = "chrono")]
1202    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
1203        T::from_postgres_timestamp(value).map(Some)
1204    }
1205
1206    #[cfg(feature = "chrono")]
1207    fn from_postgres_timestamptz(
1208        value: chrono::DateTime<chrono::FixedOffset>,
1209    ) -> Result<Self, DrizzleError> {
1210        T::from_postgres_timestamptz(value).map(Some)
1211    }
1212
1213    #[cfg(feature = "chrono")]
1214    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
1215        T::from_postgres_interval(value).map(Some)
1216    }
1217
1218    #[cfg(feature = "time")]
1219    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
1220        T::from_postgres_time_date(value).map(Some)
1221    }
1222
1223    #[cfg(feature = "time")]
1224    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
1225        T::from_postgres_time_time(value).map(Some)
1226    }
1227
1228    #[cfg(feature = "time")]
1229    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
1230        T::from_postgres_time_timestamp(value).map(Some)
1231    }
1232
1233    #[cfg(feature = "time")]
1234    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
1235        T::from_postgres_time_timestamptz(value).map(Some)
1236    }
1237
1238    #[cfg(feature = "time")]
1239    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
1240        T::from_postgres_time_interval(value).map(Some)
1241    }
1242
1243    #[cfg(feature = "jiff")]
1244    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
1245        T::from_postgres_jiff_date(value).map(Some)
1246    }
1247
1248    #[cfg(feature = "jiff")]
1249    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
1250        T::from_postgres_jiff_time(value).map(Some)
1251    }
1252
1253    #[cfg(feature = "jiff")]
1254    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
1255        T::from_postgres_jiff_datetime(value).map(Some)
1256    }
1257
1258    #[cfg(feature = "jiff")]
1259    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
1260        T::from_postgres_jiff_timestamp(value).map(Some)
1261    }
1262
1263    #[cfg(feature = "cidr")]
1264    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
1265        T::from_postgres_inet(value).map(Some)
1266    }
1267
1268    #[cfg(feature = "cidr")]
1269    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
1270        T::from_postgres_cidr(value).map(Some)
1271    }
1272
1273    #[cfg(feature = "cidr")]
1274    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
1275        T::from_postgres_macaddr(value).map(Some)
1276    }
1277
1278    #[cfg(feature = "cidr")]
1279    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
1280        T::from_postgres_macaddr8(value).map(Some)
1281    }
1282
1283    #[cfg(feature = "geo-types")]
1284    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
1285        T::from_postgres_point(value).map(Some)
1286    }
1287
1288    #[cfg(feature = "geo-types")]
1289    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
1290        T::from_postgres_linestring(value).map(Some)
1291    }
1292
1293    #[cfg(feature = "geo-types")]
1294    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
1295        T::from_postgres_rect(value).map(Some)
1296    }
1297
1298    #[cfg(feature = "bit-vec")]
1299    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
1300        T::from_postgres_bitvec(value).map(Some)
1301    }
1302
1303    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
1304        T::from_postgres_array(value).map(Some)
1305    }
1306
1307    fn from_postgres_null() -> Result<Self, DrizzleError> {
1308        Ok(None)
1309    }
1310}
1311
1312// =============================================================================
1313// Driver-specific DrizzleRow implementations
1314// =============================================================================
1315
1316// Note: postgres::Row is a re-export of tokio_postgres::Row, so we only need
1317// to implement for one type. We use tokio_postgres::Row as it's the underlying type.
1318// When only postgres-sync is enabled, postgres::Row will be available.
1319
1320#[cfg(any(feature = "postgres-sync", feature = "tokio-postgres"))]
1321mod postgres_row_impl {
1322    use super::{
1323        DrizzleError, DrizzleRowByIndex, DrizzleRowByName, FromPostgresValue, PostgresValue,
1324        String, Vec,
1325    };
1326
1327    // Helper function to convert a row value to our type
1328    // This uses the native driver's try_get functionality
1329    fn convert_column<T: FromPostgresValue, R: PostgresRowLike>(
1330        row: &R,
1331        column: impl ColumnRef,
1332    ) -> Result<T, DrizzleError> {
1333        if let Some(result) = try_oid_dispatch::<T, R>(row, &column) {
1334            return result;
1335        }
1336        if let Some(result) = try_scalar_fallbacks::<T, R>(row, &column) {
1337            return result;
1338        }
1339        if let Some(result) = try_array_fallbacks::<T, R>(row, &column) {
1340            return result;
1341        }
1342
1343        // If all type probes returned None/error, assume NULL.
1344        T::from_postgres_null()
1345    }
1346
1347    /// `PostgreSQL` OID fast-path: when the column's declared type matches a
1348    /// known primitive OID, decode directly without running the full fallback
1349    /// chain.
1350    fn try_oid_dispatch<T: FromPostgresValue, R: PostgresRowLike>(
1351        row: &R,
1352        column: &impl ColumnRef,
1353    ) -> Option<Result<T, DrizzleError>> {
1354        let oid = row.type_oid(column)?;
1355        match oid {
1356            16 => row
1357                .try_get_bool(column)
1358                .ok()
1359                .flatten()
1360                .map(T::from_postgres_bool),
1361            20 => row
1362                .try_get_i64(column)
1363                .ok()
1364                .flatten()
1365                .map(T::from_postgres_i64),
1366            23 => row
1367                .try_get_i32(column)
1368                .ok()
1369                .flatten()
1370                .map(T::from_postgres_i32),
1371            21 => row
1372                .try_get_i16(column)
1373                .ok()
1374                .flatten()
1375                .map(T::from_postgres_i16),
1376            701 => row
1377                .try_get_f64(column)
1378                .ok()
1379                .flatten()
1380                .map(T::from_postgres_f64),
1381            700 => row
1382                .try_get_f32(column)
1383                .ok()
1384                .flatten()
1385                .map(T::from_postgres_f32),
1386            17 => row
1387                .try_get_bytes(column)
1388                .ok()
1389                .flatten()
1390                .map(|v| T::from_postgres_bytes(&v)),
1391            25 | 1043 | 1042 => row
1392                .try_get_string(column)
1393                .ok()
1394                .flatten()
1395                .map(|v| T::from_postgres_text(&v)),
1396            _ => None,
1397        }
1398    }
1399
1400    /// Scalar fallback chain: try each supported primitive / library type in
1401    /// priority order, returning the first that decodes successfully.
1402    fn try_scalar_fallbacks<T: FromPostgresValue, R: PostgresRowLike>(
1403        row: &R,
1404        column: &impl ColumnRef,
1405    ) -> Option<Result<T, DrizzleError>> {
1406        try_scalar_primitives::<T, R>(row, column)
1407            .or_else(|| try_scalar_uuid::<T, R>(row, column))
1408            .or_else(|| try_scalar_json::<T, R>(row, column))
1409            .or_else(|| try_scalar_chrono::<T, R>(row, column))
1410            .or_else(|| try_scalar_cidr::<T, R>(row, column))
1411            .or_else(|| try_scalar_geo::<T, R>(row, column))
1412            .or_else(|| try_scalar_bitvec::<T, R>(row, column))
1413    }
1414
1415    /// Primitive scalar fallbacks: bool / integers / floats / text / bytes.
1416    fn try_scalar_primitives<T: FromPostgresValue, R: PostgresRowLike>(
1417        row: &R,
1418        column: &impl ColumnRef,
1419    ) -> Option<Result<T, DrizzleError>> {
1420        if let Ok(Some(v)) = row.try_get_bool(column) {
1421            return Some(T::from_postgres_bool(v));
1422        }
1423        if let Ok(Some(v)) = row.try_get_i64(column) {
1424            return Some(T::from_postgres_i64(v));
1425        }
1426        if let Ok(Some(v)) = row.try_get_i32(column) {
1427            return Some(T::from_postgres_i32(v));
1428        }
1429        if let Ok(Some(v)) = row.try_get_i16(column) {
1430            return Some(T::from_postgres_i16(v));
1431        }
1432        if let Ok(Some(v)) = row.try_get_f64(column) {
1433            return Some(T::from_postgres_f64(v));
1434        }
1435        if let Ok(Some(v)) = row.try_get_f32(column) {
1436            return Some(T::from_postgres_f32(v));
1437        }
1438        if let Ok(Some(ref v)) = row.try_get_string(column) {
1439            return Some(T::from_postgres_text(v));
1440        }
1441        if let Ok(Some(ref v)) = row.try_get_bytes(column) {
1442            return Some(T::from_postgres_bytes(v));
1443        }
1444        None
1445    }
1446
1447    #[cfg(feature = "uuid")]
1448    fn try_scalar_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1449        row: &R,
1450        column: &impl ColumnRef,
1451    ) -> Option<Result<T, DrizzleError>> {
1452        row.try_get_uuid(column)
1453            .ok()
1454            .flatten()
1455            .map(T::from_postgres_uuid)
1456    }
1457
1458    #[cfg(not(feature = "uuid"))]
1459    const fn try_scalar_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1460        _row: &R,
1461        _column: &impl ColumnRef,
1462    ) -> Option<Result<T, DrizzleError>> {
1463        None
1464    }
1465
1466    #[cfg(feature = "serde")]
1467    fn try_scalar_json<T: FromPostgresValue, R: PostgresRowLike>(
1468        row: &R,
1469        column: &impl ColumnRef,
1470    ) -> Option<Result<T, DrizzleError>> {
1471        row.try_get_json(column)
1472            .ok()
1473            .flatten()
1474            .map(T::from_postgres_json)
1475    }
1476
1477    #[cfg(not(feature = "serde"))]
1478    const fn try_scalar_json<T: FromPostgresValue, R: PostgresRowLike>(
1479        _row: &R,
1480        _column: &impl ColumnRef,
1481    ) -> Option<Result<T, DrizzleError>> {
1482        None
1483    }
1484
1485    #[cfg(feature = "chrono")]
1486    fn try_scalar_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1487        row: &R,
1488        column: &impl ColumnRef,
1489    ) -> Option<Result<T, DrizzleError>> {
1490        if let Ok(Some(v)) = row.try_get_date(column) {
1491            return Some(T::from_postgres_date(v));
1492        }
1493        if let Ok(Some(v)) = row.try_get_time(column) {
1494            return Some(T::from_postgres_time(v));
1495        }
1496        if let Ok(Some(v)) = row.try_get_timestamp(column) {
1497            return Some(T::from_postgres_timestamp(v));
1498        }
1499        if let Ok(Some(v)) = row.try_get_timestamptz(column) {
1500            return Some(T::from_postgres_timestamptz(v));
1501        }
1502        None
1503    }
1504
1505    #[cfg(not(feature = "chrono"))]
1506    const fn try_scalar_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1507        _row: &R,
1508        _column: &impl ColumnRef,
1509    ) -> Option<Result<T, DrizzleError>> {
1510        None
1511    }
1512
1513    #[cfg(feature = "cidr")]
1514    fn try_scalar_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1515        row: &R,
1516        column: &impl ColumnRef,
1517    ) -> Option<Result<T, DrizzleError>> {
1518        if let Ok(Some(v)) = row.try_get_inet(column) {
1519            return Some(T::from_postgres_inet(v));
1520        }
1521        if let Ok(Some(v)) = row.try_get_cidr(column) {
1522            return Some(T::from_postgres_cidr(v));
1523        }
1524        if let Ok(Some(v)) = row.try_get_macaddr(column) {
1525            return Some(T::from_postgres_macaddr(v));
1526        }
1527        if let Ok(Some(v)) = row.try_get_macaddr8(column) {
1528            return Some(T::from_postgres_macaddr8(v));
1529        }
1530        None
1531    }
1532
1533    #[cfg(not(feature = "cidr"))]
1534    const fn try_scalar_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1535        _row: &R,
1536        _column: &impl ColumnRef,
1537    ) -> Option<Result<T, DrizzleError>> {
1538        None
1539    }
1540
1541    #[cfg(feature = "geo-types")]
1542    fn try_scalar_geo<T: FromPostgresValue, R: PostgresRowLike>(
1543        row: &R,
1544        column: &impl ColumnRef,
1545    ) -> Option<Result<T, DrizzleError>> {
1546        if let Ok(Some(v)) = row.try_get_point(column) {
1547            return Some(T::from_postgres_point(v));
1548        }
1549        if let Ok(Some(v)) = row.try_get_linestring(column) {
1550            return Some(T::from_postgres_linestring(v));
1551        }
1552        if let Ok(Some(v)) = row.try_get_rect(column) {
1553            return Some(T::from_postgres_rect(v));
1554        }
1555        None
1556    }
1557
1558    #[cfg(not(feature = "geo-types"))]
1559    const fn try_scalar_geo<T: FromPostgresValue, R: PostgresRowLike>(
1560        _row: &R,
1561        _column: &impl ColumnRef,
1562    ) -> Option<Result<T, DrizzleError>> {
1563        None
1564    }
1565
1566    #[cfg(feature = "bit-vec")]
1567    fn try_scalar_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1568        row: &R,
1569        column: &impl ColumnRef,
1570    ) -> Option<Result<T, DrizzleError>> {
1571        row.try_get_bitvec(column)
1572            .ok()
1573            .flatten()
1574            .map(T::from_postgres_bitvec)
1575    }
1576
1577    #[cfg(not(feature = "bit-vec"))]
1578    const fn try_scalar_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1579        _row: &R,
1580        _column: &impl ColumnRef,
1581    ) -> Option<Result<T, DrizzleError>> {
1582        None
1583    }
1584
1585    /// Array fallback chain: try each supported array element type in priority
1586    /// order.
1587    fn try_array_fallbacks<T: FromPostgresValue, R: PostgresRowLike>(
1588        row: &R,
1589        column: &impl ColumnRef,
1590    ) -> Option<Result<T, DrizzleError>> {
1591        try_array_primitives::<T, R>(row, column)
1592            .or_else(|| try_array_uuid::<T, R>(row, column))
1593            .or_else(|| try_array_json::<T, R>(row, column))
1594            .or_else(|| try_array_chrono::<T, R>(row, column))
1595            .or_else(|| try_array_cidr::<T, R>(row, column))
1596            .or_else(|| try_array_geo::<T, R>(row, column))
1597            .or_else(|| try_array_bitvec::<T, R>(row, column))
1598            .or_else(|| try_array_text_bytes::<T, R>(row, column))
1599    }
1600
1601    /// Primitive array fallbacks: bool / integers / floats (priority order).
1602    fn try_array_primitives<T: FromPostgresValue, R: PostgresRowLike>(
1603        row: &R,
1604        column: &impl ColumnRef,
1605    ) -> Option<Result<T, DrizzleError>> {
1606        if let Ok(Some(values)) = row.try_get_array_bool(column) {
1607            return Some(T::from_postgres_array(array_values(values)));
1608        }
1609        if let Ok(Some(values)) = row.try_get_array_i16(column) {
1610            return Some(T::from_postgres_array(array_values(values)));
1611        }
1612        if let Ok(Some(values)) = row.try_get_array_i32(column) {
1613            return Some(T::from_postgres_array(array_values(values)));
1614        }
1615        if let Ok(Some(values)) = row.try_get_array_i64(column) {
1616            return Some(T::from_postgres_array(array_values(values)));
1617        }
1618        if let Ok(Some(values)) = row.try_get_array_f32(column) {
1619            return Some(T::from_postgres_array(array_values(values)));
1620        }
1621        if let Ok(Some(values)) = row.try_get_array_f64(column) {
1622            return Some(T::from_postgres_array(array_values(values)));
1623        }
1624        None
1625    }
1626
1627    #[cfg(feature = "uuid")]
1628    fn try_array_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1629        row: &R,
1630        column: &impl ColumnRef,
1631    ) -> Option<Result<T, DrizzleError>> {
1632        row.try_get_array_uuid(column)
1633            .ok()
1634            .flatten()
1635            .map(|values| T::from_postgres_array(array_values(values)))
1636    }
1637
1638    #[cfg(not(feature = "uuid"))]
1639    const fn try_array_uuid<T: FromPostgresValue, R: PostgresRowLike>(
1640        _row: &R,
1641        _column: &impl ColumnRef,
1642    ) -> Option<Result<T, DrizzleError>> {
1643        None
1644    }
1645
1646    #[cfg(feature = "serde")]
1647    fn try_array_json<T: FromPostgresValue, R: PostgresRowLike>(
1648        row: &R,
1649        column: &impl ColumnRef,
1650    ) -> Option<Result<T, DrizzleError>> {
1651        row.try_get_array_json(column)
1652            .ok()
1653            .flatten()
1654            .map(|values| T::from_postgres_array(array_values(values)))
1655    }
1656
1657    #[cfg(not(feature = "serde"))]
1658    const fn try_array_json<T: FromPostgresValue, R: PostgresRowLike>(
1659        _row: &R,
1660        _column: &impl ColumnRef,
1661    ) -> Option<Result<T, DrizzleError>> {
1662        None
1663    }
1664
1665    #[cfg(feature = "chrono")]
1666    fn try_array_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1667        row: &R,
1668        column: &impl ColumnRef,
1669    ) -> Option<Result<T, DrizzleError>> {
1670        if let Ok(Some(values)) = row.try_get_array_date(column) {
1671            return Some(T::from_postgres_array(array_values(values)));
1672        }
1673        if let Ok(Some(values)) = row.try_get_array_time(column) {
1674            return Some(T::from_postgres_array(array_values(values)));
1675        }
1676        if let Ok(Some(values)) = row.try_get_array_timestamp(column) {
1677            return Some(T::from_postgres_array(array_values(values)));
1678        }
1679        if let Ok(Some(values)) = row.try_get_array_timestamptz(column) {
1680            return Some(T::from_postgres_array(array_values(values)));
1681        }
1682        None
1683    }
1684
1685    #[cfg(not(feature = "chrono"))]
1686    const fn try_array_chrono<T: FromPostgresValue, R: PostgresRowLike>(
1687        _row: &R,
1688        _column: &impl ColumnRef,
1689    ) -> Option<Result<T, DrizzleError>> {
1690        None
1691    }
1692
1693    #[cfg(feature = "cidr")]
1694    fn try_array_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1695        row: &R,
1696        column: &impl ColumnRef,
1697    ) -> Option<Result<T, DrizzleError>> {
1698        if let Ok(Some(values)) = row.try_get_array_inet(column) {
1699            return Some(T::from_postgres_array(array_values(values)));
1700        }
1701        if let Ok(Some(values)) = row.try_get_array_cidr(column) {
1702            return Some(T::from_postgres_array(array_values(values)));
1703        }
1704        if let Ok(Some(values)) = row.try_get_array_macaddr(column) {
1705            return Some(T::from_postgres_array(array_values(values)));
1706        }
1707        if let Ok(Some(values)) = row.try_get_array_macaddr8(column) {
1708            return Some(T::from_postgres_array(array_values(values)));
1709        }
1710        None
1711    }
1712
1713    #[cfg(not(feature = "cidr"))]
1714    const fn try_array_cidr<T: FromPostgresValue, R: PostgresRowLike>(
1715        _row: &R,
1716        _column: &impl ColumnRef,
1717    ) -> Option<Result<T, DrizzleError>> {
1718        None
1719    }
1720
1721    #[cfg(feature = "geo-types")]
1722    fn try_array_geo<T: FromPostgresValue, R: PostgresRowLike>(
1723        row: &R,
1724        column: &impl ColumnRef,
1725    ) -> Option<Result<T, DrizzleError>> {
1726        if let Ok(Some(values)) = row.try_get_array_point(column) {
1727            return Some(T::from_postgres_array(array_values(values)));
1728        }
1729        if let Ok(Some(values)) = row.try_get_array_linestring(column) {
1730            return Some(T::from_postgres_array(array_values(values)));
1731        }
1732        if let Ok(Some(values)) = row.try_get_array_rect(column) {
1733            return Some(T::from_postgres_array(array_values(values)));
1734        }
1735        None
1736    }
1737
1738    #[cfg(not(feature = "geo-types"))]
1739    const fn try_array_geo<T: FromPostgresValue, R: PostgresRowLike>(
1740        _row: &R,
1741        _column: &impl ColumnRef,
1742    ) -> Option<Result<T, DrizzleError>> {
1743        None
1744    }
1745
1746    #[cfg(feature = "bit-vec")]
1747    fn try_array_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1748        row: &R,
1749        column: &impl ColumnRef,
1750    ) -> Option<Result<T, DrizzleError>> {
1751        row.try_get_array_bitvec(column)
1752            .ok()
1753            .flatten()
1754            .map(|values| T::from_postgres_array(array_values(values)))
1755    }
1756
1757    #[cfg(not(feature = "bit-vec"))]
1758    const fn try_array_bitvec<T: FromPostgresValue, R: PostgresRowLike>(
1759        _row: &R,
1760        _column: &impl ColumnRef,
1761    ) -> Option<Result<T, DrizzleError>> {
1762        None
1763    }
1764
1765    /// Final bytes/text array fallback (lowest priority).
1766    fn try_array_text_bytes<T: FromPostgresValue, R: PostgresRowLike>(
1767        row: &R,
1768        column: &impl ColumnRef,
1769    ) -> Option<Result<T, DrizzleError>> {
1770        if let Ok(Some(values)) = row.try_get_array_bytes(column) {
1771            return Some(T::from_postgres_array(array_values(values)));
1772        }
1773        if let Ok(Some(values)) = row.try_get_array_text(column) {
1774            return Some(T::from_postgres_array(array_values(values)));
1775        }
1776        None
1777    }
1778
1779    /// Trait for column reference types (index or name)
1780    trait ColumnRef: Copy {
1781        fn to_index(&self) -> Option<usize>;
1782        fn to_name(&self) -> Option<&str>;
1783    }
1784
1785    impl ColumnRef for usize {
1786        fn to_index(&self) -> Option<usize> {
1787            Some(*self)
1788        }
1789        fn to_name(&self) -> Option<&str> {
1790            None
1791        }
1792    }
1793
1794    impl ColumnRef for &str {
1795        fn to_index(&self) -> Option<usize> {
1796            None
1797        }
1798        fn to_name(&self) -> Option<&str> {
1799            Some(*self)
1800        }
1801    }
1802
1803    fn array_values<T>(values: Vec<Option<T>>) -> Vec<PostgresValue<'static>>
1804    where
1805        T: Into<PostgresValue<'static>>,
1806    {
1807        values
1808            .into_iter()
1809            .map(|value| value.map_or(PostgresValue::Null, Into::into))
1810            .collect()
1811    }
1812
1813    #[cfg(feature = "cidr")]
1814    fn parse_mac<const N: usize>(value: &str) -> Option<[u8; N]> {
1815        let mut bytes = [0u8; N];
1816        let mut parts = value.split(':');
1817
1818        for slot in &mut bytes {
1819            let part = parts.next()?;
1820            if part.len() != 2 {
1821                return None;
1822            }
1823            *slot = u8::from_str_radix(part, 16).ok()?;
1824        }
1825
1826        if parts.next().is_some() {
1827            return None;
1828        }
1829
1830        Some(bytes)
1831    }
1832
1833    #[cfg(feature = "cidr")]
1834    fn parse_mac_array<const N: usize>(
1835        values: Vec<Option<String>>,
1836    ) -> Result<Vec<Option<[u8; N]>>, ()> {
1837        let mut parsed = Vec::with_capacity(values.len());
1838        for value in values {
1839            match value {
1840                Some(value) => {
1841                    let parsed_value = parse_mac::<N>(&value).ok_or(())?;
1842                    parsed.push(Some(parsed_value));
1843                }
1844                None => parsed.push(None),
1845            }
1846        }
1847        Ok(parsed)
1848    }
1849
1850    /// Resolve a `ColumnRef` to either an index-based or name-based `try_get` call
1851    /// on the underlying driver `Row`, returning `Err(())` when neither key resolves.
1852    macro_rules! try_get_typed {
1853        ($self:ident, $column:ident, $ty:ty) => {
1854            match ($column.to_index(), $column.to_name()) {
1855                (Some(idx), _) => $self.try_get::<_, Option<$ty>>(idx).map_err(|_| ()),
1856                (None, Some(name)) => $self.try_get::<_, Option<$ty>>(name).map_err(|_| ()),
1857                (None, None) => Err(()),
1858            }
1859        };
1860    }
1861
1862    /// Internal trait to abstract over postgres/tokio-postgres Row types
1863    trait PostgresRowLike {
1864        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32>;
1865        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()>;
1866        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()>;
1867        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()>;
1868        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()>;
1869        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()>;
1870        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()>;
1871        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()>;
1872        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()>;
1873        #[cfg(feature = "uuid")]
1874        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()>;
1875        #[cfg(feature = "serde")]
1876        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()>;
1877        #[cfg(feature = "chrono")]
1878        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()>;
1879        #[cfg(feature = "chrono")]
1880        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()>;
1881        #[cfg(feature = "chrono")]
1882        fn try_get_timestamp(
1883            &self,
1884            column: &impl ColumnRef,
1885        ) -> Result<Option<chrono::NaiveDateTime>, ()>;
1886        #[cfg(feature = "chrono")]
1887        fn try_get_timestamptz(
1888            &self,
1889            column: &impl ColumnRef,
1890        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()>;
1891        #[cfg(feature = "cidr")]
1892        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()>;
1893        #[cfg(feature = "cidr")]
1894        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()>;
1895        #[cfg(feature = "cidr")]
1896        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()>;
1897        #[cfg(feature = "cidr")]
1898        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()>;
1899        #[cfg(feature = "geo-types")]
1900        fn try_get_point(
1901            &self,
1902            column: &impl ColumnRef,
1903        ) -> Result<Option<geo_types::Point<f64>>, ()>;
1904        #[cfg(feature = "geo-types")]
1905        fn try_get_linestring(
1906            &self,
1907            column: &impl ColumnRef,
1908        ) -> Result<Option<geo_types::LineString<f64>>, ()>;
1909        #[cfg(feature = "geo-types")]
1910        fn try_get_rect(&self, column: &impl ColumnRef)
1911        -> Result<Option<geo_types::Rect<f64>>, ()>;
1912        #[cfg(feature = "bit-vec")]
1913        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()>;
1914
1915        fn try_get_array_bool(
1916            &self,
1917            column: &impl ColumnRef,
1918        ) -> Result<Option<Vec<Option<bool>>>, ()>;
1919        fn try_get_array_i16(
1920            &self,
1921            column: &impl ColumnRef,
1922        ) -> Result<Option<Vec<Option<i16>>>, ()>;
1923        fn try_get_array_i32(
1924            &self,
1925            column: &impl ColumnRef,
1926        ) -> Result<Option<Vec<Option<i32>>>, ()>;
1927        fn try_get_array_i64(
1928            &self,
1929            column: &impl ColumnRef,
1930        ) -> Result<Option<Vec<Option<i64>>>, ()>;
1931        fn try_get_array_f32(
1932            &self,
1933            column: &impl ColumnRef,
1934        ) -> Result<Option<Vec<Option<f32>>>, ()>;
1935        fn try_get_array_f64(
1936            &self,
1937            column: &impl ColumnRef,
1938        ) -> Result<Option<Vec<Option<f64>>>, ()>;
1939        fn try_get_array_text(
1940            &self,
1941            column: &impl ColumnRef,
1942        ) -> Result<Option<Vec<Option<String>>>, ()>;
1943        fn try_get_array_bytes(
1944            &self,
1945            column: &impl ColumnRef,
1946        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()>;
1947        #[cfg(feature = "uuid")]
1948        fn try_get_array_uuid(
1949            &self,
1950            column: &impl ColumnRef,
1951        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()>;
1952        #[cfg(feature = "serde")]
1953        fn try_get_array_json(
1954            &self,
1955            column: &impl ColumnRef,
1956        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()>;
1957        #[cfg(feature = "chrono")]
1958        fn try_get_array_date(
1959            &self,
1960            column: &impl ColumnRef,
1961        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()>;
1962        #[cfg(feature = "chrono")]
1963        fn try_get_array_time(
1964            &self,
1965            column: &impl ColumnRef,
1966        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()>;
1967        #[cfg(feature = "chrono")]
1968        fn try_get_array_timestamp(
1969            &self,
1970            column: &impl ColumnRef,
1971        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()>;
1972        #[cfg(feature = "chrono")]
1973        fn try_get_array_timestamptz(
1974            &self,
1975            column: &impl ColumnRef,
1976        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()>;
1977        #[cfg(feature = "cidr")]
1978        fn try_get_array_inet(
1979            &self,
1980            column: &impl ColumnRef,
1981        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()>;
1982        #[cfg(feature = "cidr")]
1983        fn try_get_array_cidr(
1984            &self,
1985            column: &impl ColumnRef,
1986        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()>;
1987        #[cfg(feature = "cidr")]
1988        fn try_get_array_macaddr(
1989            &self,
1990            column: &impl ColumnRef,
1991        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()>;
1992        #[cfg(feature = "cidr")]
1993        fn try_get_array_macaddr8(
1994            &self,
1995            column: &impl ColumnRef,
1996        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()>;
1997        #[cfg(feature = "geo-types")]
1998        fn try_get_array_point(
1999            &self,
2000            column: &impl ColumnRef,
2001        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()>;
2002        #[cfg(feature = "geo-types")]
2003        fn try_get_array_linestring(
2004            &self,
2005            column: &impl ColumnRef,
2006        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()>;
2007        #[cfg(feature = "geo-types")]
2008        fn try_get_array_rect(
2009            &self,
2010            column: &impl ColumnRef,
2011        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()>;
2012        #[cfg(feature = "bit-vec")]
2013        fn try_get_array_bitvec(
2014            &self,
2015            column: &impl ColumnRef,
2016        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()>;
2017    }
2018
2019    // Use tokio_postgres when available, postgres when not
2020    #[cfg(feature = "tokio-postgres")]
2021    impl PostgresRowLike for tokio_postgres::Row {
2022        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32> {
2023            let idx = match (column.to_index(), column.to_name()) {
2024                (Some(idx), _) => idx,
2025                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2026                (None, None) => return None,
2027            };
2028
2029            self.columns().get(idx).map(|c| c.type_().oid())
2030        }
2031
2032        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()> {
2033            try_get_typed!(self, column, bool)
2034        }
2035
2036        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()> {
2037            try_get_typed!(self, column, i16)
2038        }
2039
2040        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()> {
2041            try_get_typed!(self, column, i32)
2042        }
2043
2044        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()> {
2045            try_get_typed!(self, column, i64)
2046        }
2047
2048        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()> {
2049            try_get_typed!(self, column, f32)
2050        }
2051
2052        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()> {
2053            try_get_typed!(self, column, f64)
2054        }
2055
2056        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()> {
2057            try_get_typed!(self, column, String)
2058        }
2059
2060        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()> {
2061            try_get_typed!(self, column, Vec<u8>)
2062        }
2063
2064        #[cfg(feature = "uuid")]
2065        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()> {
2066            try_get_typed!(self, column, uuid::Uuid)
2067        }
2068
2069        #[cfg(feature = "serde")]
2070        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()> {
2071            try_get_typed!(self, column, serde_json::Value)
2072        }
2073
2074        #[cfg(feature = "chrono")]
2075        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()> {
2076            try_get_typed!(self, column, chrono::NaiveDate)
2077        }
2078
2079        #[cfg(feature = "chrono")]
2080        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()> {
2081            try_get_typed!(self, column, chrono::NaiveTime)
2082        }
2083
2084        #[cfg(feature = "chrono")]
2085        fn try_get_timestamp(
2086            &self,
2087            column: &impl ColumnRef,
2088        ) -> Result<Option<chrono::NaiveDateTime>, ()> {
2089            try_get_typed!(self, column, chrono::NaiveDateTime)
2090        }
2091
2092        #[cfg(feature = "chrono")]
2093        fn try_get_timestamptz(
2094            &self,
2095            column: &impl ColumnRef,
2096        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()> {
2097            try_get_typed!(self, column, chrono::DateTime<chrono::FixedOffset>)
2098        }
2099
2100        #[cfg(feature = "cidr")]
2101        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()> {
2102            try_get_typed!(self, column, cidr::IpInet)
2103        }
2104
2105        #[cfg(feature = "cidr")]
2106        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()> {
2107            try_get_typed!(self, column, cidr::IpCidr)
2108        }
2109
2110        #[cfg(feature = "cidr")]
2111        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()> {
2112            match self.try_get_string(column) {
2113                Ok(Some(value)) => parse_mac::<6>(&value).ok_or(()).map(Some),
2114                Ok(None) => Ok(None),
2115                Err(()) => Err(()),
2116            }
2117        }
2118
2119        #[cfg(feature = "cidr")]
2120        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()> {
2121            match self.try_get_string(column) {
2122                Ok(Some(value)) => parse_mac::<8>(&value).ok_or(()).map(Some),
2123                Ok(None) => Ok(None),
2124                Err(()) => Err(()),
2125            }
2126        }
2127
2128        #[cfg(feature = "geo-types")]
2129        fn try_get_point(
2130            &self,
2131            column: &impl ColumnRef,
2132        ) -> Result<Option<geo_types::Point<f64>>, ()> {
2133            try_get_typed!(self, column, geo_types::Point<f64>)
2134        }
2135
2136        #[cfg(feature = "geo-types")]
2137        fn try_get_linestring(
2138            &self,
2139            column: &impl ColumnRef,
2140        ) -> Result<Option<geo_types::LineString<f64>>, ()> {
2141            try_get_typed!(self, column, geo_types::LineString<f64>)
2142        }
2143
2144        #[cfg(feature = "geo-types")]
2145        fn try_get_rect(
2146            &self,
2147            column: &impl ColumnRef,
2148        ) -> Result<Option<geo_types::Rect<f64>>, ()> {
2149            try_get_typed!(self, column, geo_types::Rect<f64>)
2150        }
2151
2152        #[cfg(feature = "bit-vec")]
2153        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()> {
2154            try_get_typed!(self, column, bit_vec::BitVec)
2155        }
2156
2157        fn try_get_array_bool(
2158            &self,
2159            column: &impl ColumnRef,
2160        ) -> Result<Option<Vec<Option<bool>>>, ()> {
2161            try_get_typed!(self, column, Vec<Option<bool>>)
2162        }
2163
2164        fn try_get_array_i16(
2165            &self,
2166            column: &impl ColumnRef,
2167        ) -> Result<Option<Vec<Option<i16>>>, ()> {
2168            try_get_typed!(self, column, Vec<Option<i16>>)
2169        }
2170
2171        fn try_get_array_i32(
2172            &self,
2173            column: &impl ColumnRef,
2174        ) -> Result<Option<Vec<Option<i32>>>, ()> {
2175            try_get_typed!(self, column, Vec<Option<i32>>)
2176        }
2177
2178        fn try_get_array_i64(
2179            &self,
2180            column: &impl ColumnRef,
2181        ) -> Result<Option<Vec<Option<i64>>>, ()> {
2182            try_get_typed!(self, column, Vec<Option<i64>>)
2183        }
2184
2185        fn try_get_array_f32(
2186            &self,
2187            column: &impl ColumnRef,
2188        ) -> Result<Option<Vec<Option<f32>>>, ()> {
2189            try_get_typed!(self, column, Vec<Option<f32>>)
2190        }
2191
2192        fn try_get_array_f64(
2193            &self,
2194            column: &impl ColumnRef,
2195        ) -> Result<Option<Vec<Option<f64>>>, ()> {
2196            try_get_typed!(self, column, Vec<Option<f64>>)
2197        }
2198
2199        fn try_get_array_text(
2200            &self,
2201            column: &impl ColumnRef,
2202        ) -> Result<Option<Vec<Option<String>>>, ()> {
2203            try_get_typed!(self, column, Vec<Option<String>>)
2204        }
2205
2206        fn try_get_array_bytes(
2207            &self,
2208            column: &impl ColumnRef,
2209        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()> {
2210            try_get_typed!(self, column, Vec<Option<Vec<u8>>>)
2211        }
2212
2213        #[cfg(feature = "uuid")]
2214        fn try_get_array_uuid(
2215            &self,
2216            column: &impl ColumnRef,
2217        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()> {
2218            try_get_typed!(self, column, Vec<Option<uuid::Uuid>>)
2219        }
2220
2221        #[cfg(feature = "serde")]
2222        fn try_get_array_json(
2223            &self,
2224            column: &impl ColumnRef,
2225        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()> {
2226            try_get_typed!(self, column, Vec<Option<serde_json::Value>>)
2227        }
2228
2229        #[cfg(feature = "chrono")]
2230        fn try_get_array_date(
2231            &self,
2232            column: &impl ColumnRef,
2233        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()> {
2234            try_get_typed!(self, column, Vec<Option<chrono::NaiveDate>>)
2235        }
2236
2237        #[cfg(feature = "chrono")]
2238        fn try_get_array_time(
2239            &self,
2240            column: &impl ColumnRef,
2241        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()> {
2242            try_get_typed!(self, column, Vec<Option<chrono::NaiveTime>>)
2243        }
2244
2245        #[cfg(feature = "chrono")]
2246        fn try_get_array_timestamp(
2247            &self,
2248            column: &impl ColumnRef,
2249        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()> {
2250            try_get_typed!(self, column, Vec<Option<chrono::NaiveDateTime>>)
2251        }
2252
2253        #[cfg(feature = "chrono")]
2254        fn try_get_array_timestamptz(
2255            &self,
2256            column: &impl ColumnRef,
2257        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()> {
2258            try_get_typed!(
2259                self,
2260                column,
2261                Vec<Option<chrono::DateTime<chrono::FixedOffset>>>
2262            )
2263        }
2264
2265        #[cfg(feature = "cidr")]
2266        fn try_get_array_inet(
2267            &self,
2268            column: &impl ColumnRef,
2269        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()> {
2270            try_get_typed!(self, column, Vec<Option<cidr::IpInet>>)
2271        }
2272
2273        #[cfg(feature = "cidr")]
2274        fn try_get_array_cidr(
2275            &self,
2276            column: &impl ColumnRef,
2277        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()> {
2278            try_get_typed!(self, column, Vec<Option<cidr::IpCidr>>)
2279        }
2280
2281        #[cfg(feature = "cidr")]
2282        fn try_get_array_macaddr(
2283            &self,
2284            column: &impl ColumnRef,
2285        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()> {
2286            match self.try_get_array_text(column) {
2287                Ok(Some(values)) => parse_mac_array::<6>(values).map(Some),
2288                Ok(None) => Ok(None),
2289                Err(()) => Err(()),
2290            }
2291        }
2292
2293        #[cfg(feature = "cidr")]
2294        fn try_get_array_macaddr8(
2295            &self,
2296            column: &impl ColumnRef,
2297        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()> {
2298            match self.try_get_array_text(column) {
2299                Ok(Some(values)) => parse_mac_array::<8>(values).map(Some),
2300                Ok(None) => Ok(None),
2301                Err(()) => Err(()),
2302            }
2303        }
2304
2305        #[cfg(feature = "geo-types")]
2306        fn try_get_array_point(
2307            &self,
2308            column: &impl ColumnRef,
2309        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()> {
2310            try_get_typed!(self, column, Vec<Option<geo_types::Point<f64>>>)
2311        }
2312
2313        #[cfg(feature = "geo-types")]
2314        fn try_get_array_linestring(
2315            &self,
2316            column: &impl ColumnRef,
2317        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()> {
2318            try_get_typed!(self, column, Vec<Option<geo_types::LineString<f64>>>)
2319        }
2320
2321        #[cfg(feature = "geo-types")]
2322        fn try_get_array_rect(
2323            &self,
2324            column: &impl ColumnRef,
2325        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()> {
2326            try_get_typed!(self, column, Vec<Option<geo_types::Rect<f64>>>)
2327        }
2328
2329        #[cfg(feature = "bit-vec")]
2330        fn try_get_array_bitvec(
2331            &self,
2332            column: &impl ColumnRef,
2333        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()> {
2334            try_get_typed!(self, column, Vec<Option<bit_vec::BitVec>>)
2335        }
2336    }
2337
2338    #[cfg(feature = "tokio-postgres")]
2339    impl DrizzleRowByIndex for tokio_postgres::Row {
2340        fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError> {
2341            convert_column(self, idx)
2342        }
2343    }
2344
2345    #[cfg(feature = "tokio-postgres")]
2346    impl DrizzleRowByName for tokio_postgres::Row {
2347        fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError> {
2348            convert_column(self, name)
2349        }
2350    }
2351
2352    // postgres::Row is a re-export of tokio_postgres::Row, so when both features
2353    // are enabled, this implementation applies to both. When only postgres-sync
2354    // is enabled, we need a separate implementation.
2355    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2356    impl PostgresRowLike for postgres::Row {
2357        fn type_oid(&self, column: &impl ColumnRef) -> Option<u32> {
2358            let idx = match (column.to_index(), column.to_name()) {
2359                (Some(idx), _) => idx,
2360                (None, Some(name)) => self.columns().iter().position(|c| c.name() == name)?,
2361                (None, None) => return None,
2362            };
2363
2364            self.columns().get(idx).map(|c| c.type_().oid())
2365        }
2366
2367        fn try_get_bool(&self, column: &impl ColumnRef) -> Result<Option<bool>, ()> {
2368            try_get_typed!(self, column, bool)
2369        }
2370
2371        fn try_get_i16(&self, column: &impl ColumnRef) -> Result<Option<i16>, ()> {
2372            try_get_typed!(self, column, i16)
2373        }
2374
2375        fn try_get_i32(&self, column: &impl ColumnRef) -> Result<Option<i32>, ()> {
2376            try_get_typed!(self, column, i32)
2377        }
2378
2379        fn try_get_i64(&self, column: &impl ColumnRef) -> Result<Option<i64>, ()> {
2380            try_get_typed!(self, column, i64)
2381        }
2382
2383        fn try_get_f32(&self, column: &impl ColumnRef) -> Result<Option<f32>, ()> {
2384            try_get_typed!(self, column, f32)
2385        }
2386
2387        fn try_get_f64(&self, column: &impl ColumnRef) -> Result<Option<f64>, ()> {
2388            try_get_typed!(self, column, f64)
2389        }
2390
2391        fn try_get_string(&self, column: &impl ColumnRef) -> Result<Option<String>, ()> {
2392            try_get_typed!(self, column, String)
2393        }
2394
2395        fn try_get_bytes(&self, column: &impl ColumnRef) -> Result<Option<Vec<u8>>, ()> {
2396            try_get_typed!(self, column, Vec<u8>)
2397        }
2398
2399        #[cfg(feature = "uuid")]
2400        fn try_get_uuid(&self, column: &impl ColumnRef) -> Result<Option<uuid::Uuid>, ()> {
2401            try_get_typed!(self, column, uuid::Uuid)
2402        }
2403
2404        #[cfg(feature = "serde")]
2405        fn try_get_json(&self, column: &impl ColumnRef) -> Result<Option<serde_json::Value>, ()> {
2406            try_get_typed!(self, column, serde_json::Value)
2407        }
2408
2409        #[cfg(feature = "chrono")]
2410        fn try_get_date(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveDate>, ()> {
2411            try_get_typed!(self, column, chrono::NaiveDate)
2412        }
2413
2414        #[cfg(feature = "chrono")]
2415        fn try_get_time(&self, column: &impl ColumnRef) -> Result<Option<chrono::NaiveTime>, ()> {
2416            try_get_typed!(self, column, chrono::NaiveTime)
2417        }
2418
2419        #[cfg(feature = "chrono")]
2420        fn try_get_timestamp(
2421            &self,
2422            column: &impl ColumnRef,
2423        ) -> Result<Option<chrono::NaiveDateTime>, ()> {
2424            try_get_typed!(self, column, chrono::NaiveDateTime)
2425        }
2426
2427        #[cfg(feature = "chrono")]
2428        fn try_get_timestamptz(
2429            &self,
2430            column: &impl ColumnRef,
2431        ) -> Result<Option<chrono::DateTime<chrono::FixedOffset>>, ()> {
2432            try_get_typed!(self, column, chrono::DateTime<chrono::FixedOffset>)
2433        }
2434
2435        #[cfg(feature = "cidr")]
2436        fn try_get_inet(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpInet>, ()> {
2437            try_get_typed!(self, column, cidr::IpInet)
2438        }
2439
2440        #[cfg(feature = "cidr")]
2441        fn try_get_cidr(&self, column: &impl ColumnRef) -> Result<Option<cidr::IpCidr>, ()> {
2442            try_get_typed!(self, column, cidr::IpCidr)
2443        }
2444
2445        #[cfg(feature = "cidr")]
2446        fn try_get_macaddr(&self, column: &impl ColumnRef) -> Result<Option<[u8; 6]>, ()> {
2447            match self.try_get_string(column) {
2448                Ok(Some(value)) => parse_mac::<6>(&value).ok_or(()).map(Some),
2449                Ok(None) => Ok(None),
2450                Err(()) => Err(()),
2451            }
2452        }
2453
2454        #[cfg(feature = "cidr")]
2455        fn try_get_macaddr8(&self, column: &impl ColumnRef) -> Result<Option<[u8; 8]>, ()> {
2456            match self.try_get_string(column) {
2457                Ok(Some(value)) => parse_mac::<8>(&value).ok_or(()).map(Some),
2458                Ok(None) => Ok(None),
2459                Err(()) => Err(()),
2460            }
2461        }
2462
2463        #[cfg(feature = "geo-types")]
2464        fn try_get_point(
2465            &self,
2466            column: &impl ColumnRef,
2467        ) -> Result<Option<geo_types::Point<f64>>, ()> {
2468            try_get_typed!(self, column, geo_types::Point<f64>)
2469        }
2470
2471        #[cfg(feature = "geo-types")]
2472        fn try_get_linestring(
2473            &self,
2474            column: &impl ColumnRef,
2475        ) -> Result<Option<geo_types::LineString<f64>>, ()> {
2476            try_get_typed!(self, column, geo_types::LineString<f64>)
2477        }
2478
2479        #[cfg(feature = "geo-types")]
2480        fn try_get_rect(
2481            &self,
2482            column: &impl ColumnRef,
2483        ) -> Result<Option<geo_types::Rect<f64>>, ()> {
2484            try_get_typed!(self, column, geo_types::Rect<f64>)
2485        }
2486
2487        #[cfg(feature = "bit-vec")]
2488        fn try_get_bitvec(&self, column: &impl ColumnRef) -> Result<Option<bit_vec::BitVec>, ()> {
2489            try_get_typed!(self, column, bit_vec::BitVec)
2490        }
2491
2492        fn try_get_array_bool(
2493            &self,
2494            column: &impl ColumnRef,
2495        ) -> Result<Option<Vec<Option<bool>>>, ()> {
2496            try_get_typed!(self, column, Vec<Option<bool>>)
2497        }
2498
2499        fn try_get_array_i16(
2500            &self,
2501            column: &impl ColumnRef,
2502        ) -> Result<Option<Vec<Option<i16>>>, ()> {
2503            try_get_typed!(self, column, Vec<Option<i16>>)
2504        }
2505
2506        fn try_get_array_i32(
2507            &self,
2508            column: &impl ColumnRef,
2509        ) -> Result<Option<Vec<Option<i32>>>, ()> {
2510            try_get_typed!(self, column, Vec<Option<i32>>)
2511        }
2512
2513        fn try_get_array_i64(
2514            &self,
2515            column: &impl ColumnRef,
2516        ) -> Result<Option<Vec<Option<i64>>>, ()> {
2517            try_get_typed!(self, column, Vec<Option<i64>>)
2518        }
2519
2520        fn try_get_array_f32(
2521            &self,
2522            column: &impl ColumnRef,
2523        ) -> Result<Option<Vec<Option<f32>>>, ()> {
2524            try_get_typed!(self, column, Vec<Option<f32>>)
2525        }
2526
2527        fn try_get_array_f64(
2528            &self,
2529            column: &impl ColumnRef,
2530        ) -> Result<Option<Vec<Option<f64>>>, ()> {
2531            try_get_typed!(self, column, Vec<Option<f64>>)
2532        }
2533
2534        fn try_get_array_text(
2535            &self,
2536            column: &impl ColumnRef,
2537        ) -> Result<Option<Vec<Option<String>>>, ()> {
2538            try_get_typed!(self, column, Vec<Option<String>>)
2539        }
2540
2541        fn try_get_array_bytes(
2542            &self,
2543            column: &impl ColumnRef,
2544        ) -> Result<Option<Vec<Option<Vec<u8>>>>, ()> {
2545            try_get_typed!(self, column, Vec<Option<Vec<u8>>>)
2546        }
2547
2548        #[cfg(feature = "uuid")]
2549        fn try_get_array_uuid(
2550            &self,
2551            column: &impl ColumnRef,
2552        ) -> Result<Option<Vec<Option<uuid::Uuid>>>, ()> {
2553            try_get_typed!(self, column, Vec<Option<uuid::Uuid>>)
2554        }
2555
2556        #[cfg(feature = "serde")]
2557        fn try_get_array_json(
2558            &self,
2559            column: &impl ColumnRef,
2560        ) -> Result<Option<Vec<Option<serde_json::Value>>>, ()> {
2561            try_get_typed!(self, column, Vec<Option<serde_json::Value>>)
2562        }
2563
2564        #[cfg(feature = "chrono")]
2565        fn try_get_array_date(
2566            &self,
2567            column: &impl ColumnRef,
2568        ) -> Result<Option<Vec<Option<chrono::NaiveDate>>>, ()> {
2569            try_get_typed!(self, column, Vec<Option<chrono::NaiveDate>>)
2570        }
2571
2572        #[cfg(feature = "chrono")]
2573        fn try_get_array_time(
2574            &self,
2575            column: &impl ColumnRef,
2576        ) -> Result<Option<Vec<Option<chrono::NaiveTime>>>, ()> {
2577            try_get_typed!(self, column, Vec<Option<chrono::NaiveTime>>)
2578        }
2579
2580        #[cfg(feature = "chrono")]
2581        fn try_get_array_timestamp(
2582            &self,
2583            column: &impl ColumnRef,
2584        ) -> Result<Option<Vec<Option<chrono::NaiveDateTime>>>, ()> {
2585            try_get_typed!(self, column, Vec<Option<chrono::NaiveDateTime>>)
2586        }
2587
2588        #[cfg(feature = "chrono")]
2589        fn try_get_array_timestamptz(
2590            &self,
2591            column: &impl ColumnRef,
2592        ) -> Result<Option<Vec<Option<chrono::DateTime<chrono::FixedOffset>>>>, ()> {
2593            try_get_typed!(
2594                self,
2595                column,
2596                Vec<Option<chrono::DateTime<chrono::FixedOffset>>>
2597            )
2598        }
2599
2600        #[cfg(feature = "cidr")]
2601        fn try_get_array_inet(
2602            &self,
2603            column: &impl ColumnRef,
2604        ) -> Result<Option<Vec<Option<cidr::IpInet>>>, ()> {
2605            try_get_typed!(self, column, Vec<Option<cidr::IpInet>>)
2606        }
2607
2608        #[cfg(feature = "cidr")]
2609        fn try_get_array_cidr(
2610            &self,
2611            column: &impl ColumnRef,
2612        ) -> Result<Option<Vec<Option<cidr::IpCidr>>>, ()> {
2613            try_get_typed!(self, column, Vec<Option<cidr::IpCidr>>)
2614        }
2615
2616        #[cfg(feature = "cidr")]
2617        fn try_get_array_macaddr(
2618            &self,
2619            column: &impl ColumnRef,
2620        ) -> Result<Option<Vec<Option<[u8; 6]>>>, ()> {
2621            match self.try_get_array_text(column) {
2622                Ok(Some(values)) => parse_mac_array::<6>(values).map(Some),
2623                Ok(None) => Ok(None),
2624                Err(()) => Err(()),
2625            }
2626        }
2627
2628        #[cfg(feature = "cidr")]
2629        fn try_get_array_macaddr8(
2630            &self,
2631            column: &impl ColumnRef,
2632        ) -> Result<Option<Vec<Option<[u8; 8]>>>, ()> {
2633            match self.try_get_array_text(column) {
2634                Ok(Some(values)) => parse_mac_array::<8>(values).map(Some),
2635                Ok(None) => Ok(None),
2636                Err(()) => Err(()),
2637            }
2638        }
2639
2640        #[cfg(feature = "geo-types")]
2641        fn try_get_array_point(
2642            &self,
2643            column: &impl ColumnRef,
2644        ) -> Result<Option<Vec<Option<geo_types::Point<f64>>>>, ()> {
2645            try_get_typed!(self, column, Vec<Option<geo_types::Point<f64>>>)
2646        }
2647
2648        #[cfg(feature = "geo-types")]
2649        fn try_get_array_linestring(
2650            &self,
2651            column: &impl ColumnRef,
2652        ) -> Result<Option<Vec<Option<geo_types::LineString<f64>>>>, ()> {
2653            try_get_typed!(self, column, Vec<Option<geo_types::LineString<f64>>>)
2654        }
2655
2656        #[cfg(feature = "geo-types")]
2657        fn try_get_array_rect(
2658            &self,
2659            column: &impl ColumnRef,
2660        ) -> Result<Option<Vec<Option<geo_types::Rect<f64>>>>, ()> {
2661            try_get_typed!(self, column, Vec<Option<geo_types::Rect<f64>>>)
2662        }
2663
2664        #[cfg(feature = "bit-vec")]
2665        fn try_get_array_bitvec(
2666            &self,
2667            column: &impl ColumnRef,
2668        ) -> Result<Option<Vec<Option<bit_vec::BitVec>>>, ()> {
2669            try_get_typed!(self, column, Vec<Option<bit_vec::BitVec>>)
2670        }
2671    }
2672
2673    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2674    impl DrizzleRowByIndex for postgres::Row {
2675        fn get_column<T: FromPostgresValue>(&self, idx: usize) -> Result<T, DrizzleError> {
2676            convert_column(self, idx)
2677        }
2678    }
2679
2680    #[cfg(all(feature = "postgres-sync", not(feature = "tokio-postgres")))]
2681    impl DrizzleRowByName for postgres::Row {
2682        fn get_column_by_name<T: FromPostgresValue>(&self, name: &str) -> Result<T, DrizzleError> {
2683            convert_column(self, name)
2684        }
2685    }
2686}
2687
2688// =============================================================================
2689// UUID support (when feature enabled)
2690// =============================================================================
2691
2692#[cfg(feature = "uuid")]
2693impl FromPostgresValue for uuid::Uuid {
2694    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2695        Err(DrizzleError::ConversionError(
2696            "cannot convert bool to UUID".into(),
2697        ))
2698    }
2699
2700    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2701        Err(DrizzleError::ConversionError(
2702            "cannot convert i16 to UUID".into(),
2703        ))
2704    }
2705
2706    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2707        Err(DrizzleError::ConversionError(
2708            "cannot convert i32 to UUID".into(),
2709        ))
2710    }
2711
2712    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2713        Err(DrizzleError::ConversionError(
2714            "cannot convert i64 to UUID".into(),
2715        ))
2716    }
2717
2718    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2719        Err(DrizzleError::ConversionError(
2720            "cannot convert f32 to UUID".into(),
2721        ))
2722    }
2723
2724    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2725        Err(DrizzleError::ConversionError(
2726            "cannot convert f64 to UUID".into(),
2727        ))
2728    }
2729
2730    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
2731        Self::parse_str(value).map_err(|e| {
2732            DrizzleError::ConversionError(format!("invalid UUID string '{value}': {e}").into())
2733        })
2734    }
2735
2736    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
2737        Self::from_slice(value)
2738            .map_err(|e| DrizzleError::ConversionError(format!("invalid UUID bytes: {e}").into()))
2739    }
2740
2741    fn from_postgres_uuid(value: uuid::Uuid) -> Result<Self, DrizzleError> {
2742        Ok(value)
2743    }
2744}
2745
2746macro_rules! impl_from_postgres_value_errors {
2747    ($target:expr) => {
2748        fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2749            Err(DrizzleError::ConversionError(
2750                format!("cannot convert bool to {}", $target).into(),
2751            ))
2752        }
2753
2754        fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2755            Err(DrizzleError::ConversionError(
2756                format!("cannot convert i16 to {}", $target).into(),
2757            ))
2758        }
2759
2760        fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2761            Err(DrizzleError::ConversionError(
2762                format!("cannot convert i32 to {}", $target).into(),
2763            ))
2764        }
2765
2766        fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2767            Err(DrizzleError::ConversionError(
2768                format!("cannot convert i64 to {}", $target).into(),
2769            ))
2770        }
2771
2772        fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2773            Err(DrizzleError::ConversionError(
2774                format!("cannot convert f32 to {}", $target).into(),
2775            ))
2776        }
2777
2778        fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2779            Err(DrizzleError::ConversionError(
2780                format!("cannot convert f64 to {}", $target).into(),
2781            ))
2782        }
2783
2784        fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
2785            Err(DrizzleError::ConversionError(
2786                format!("cannot convert text to {}", $target).into(),
2787            ))
2788        }
2789
2790        fn from_postgres_bytes(_value: &[u8]) -> Result<Self, DrizzleError> {
2791            Err(DrizzleError::ConversionError(
2792                format!("cannot convert bytes to {}", $target).into(),
2793            ))
2794        }
2795    };
2796}
2797
2798// =============================================================================
2799// PostgresEnum support
2800// =============================================================================
2801
2802impl<T> FromPostgresValue for T
2803where
2804    T: super::PostgresEnum,
2805{
2806    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
2807        Err(DrizzleError::ConversionError(
2808            "cannot convert bool to PostgresEnum".into(),
2809        ))
2810    }
2811
2812    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
2813        Err(DrizzleError::ConversionError(
2814            "cannot convert i16 to PostgresEnum".into(),
2815        ))
2816    }
2817
2818    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
2819        Err(DrizzleError::ConversionError(
2820            "cannot convert i32 to PostgresEnum".into(),
2821        ))
2822    }
2823
2824    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
2825        Err(DrizzleError::ConversionError(
2826            "cannot convert i64 to PostgresEnum".into(),
2827        ))
2828    }
2829
2830    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
2831        Err(DrizzleError::ConversionError(
2832            "cannot convert f32 to PostgresEnum".into(),
2833        ))
2834    }
2835
2836    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
2837        Err(DrizzleError::ConversionError(
2838            "cannot convert f64 to PostgresEnum".into(),
2839        ))
2840    }
2841
2842    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
2843        T::try_from_str(value)
2844    }
2845
2846    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
2847        let s = core::str::from_utf8(value).map_err(|e| {
2848            DrizzleError::ConversionError(format!("invalid UTF-8 for enum: {e}").into())
2849        })?;
2850        T::try_from_str(s)
2851    }
2852}
2853
2854// =============================================================================
2855// ARRAY support
2856// =============================================================================
2857
2858impl FromPostgresValue for Vec<PostgresValue<'_>> {
2859    impl_from_postgres_value_errors!("ARRAY");
2860
2861    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
2862        let values = value
2863            .into_iter()
2864            .map(OwnedPostgresValue::from)
2865            .map(PostgresValue::from)
2866            .collect();
2867        Ok(values)
2868    }
2869}
2870
2871impl FromPostgresValue for Vec<OwnedPostgresValue> {
2872    impl_from_postgres_value_errors!("ARRAY");
2873
2874    fn from_postgres_array(value: Vec<PostgresValue<'_>>) -> Result<Self, DrizzleError> {
2875        Ok(value.into_iter().map(OwnedPostgresValue::from).collect())
2876    }
2877}
2878
2879// =============================================================================
2880// JSON support (when feature enabled)
2881// =============================================================================
2882
2883#[cfg(feature = "serde")]
2884impl FromPostgresValue for serde_json::Value {
2885    impl_from_postgres_value_errors!("JSON");
2886
2887    fn from_postgres_json(value: serde_json::Value) -> Result<Self, DrizzleError> {
2888        Ok(value)
2889    }
2890
2891    fn from_postgres_jsonb(value: serde_json::Value) -> Result<Self, DrizzleError> {
2892        Ok(value)
2893    }
2894}
2895
2896// =============================================================================
2897// Chrono support (when feature enabled)
2898// =============================================================================
2899
2900#[cfg(feature = "chrono")]
2901impl FromPostgresValue for chrono::NaiveDate {
2902    impl_from_postgres_value_errors!("NaiveDate");
2903
2904    fn from_postgres_date(value: chrono::NaiveDate) -> Result<Self, DrizzleError> {
2905        Ok(value)
2906    }
2907}
2908
2909#[cfg(feature = "chrono")]
2910impl FromPostgresValue for chrono::NaiveTime {
2911    impl_from_postgres_value_errors!("NaiveTime");
2912
2913    fn from_postgres_time(value: chrono::NaiveTime) -> Result<Self, DrizzleError> {
2914        Ok(value)
2915    }
2916}
2917
2918#[cfg(feature = "chrono")]
2919impl FromPostgresValue for chrono::NaiveDateTime {
2920    impl_from_postgres_value_errors!("NaiveDateTime");
2921
2922    fn from_postgres_timestamp(value: chrono::NaiveDateTime) -> Result<Self, DrizzleError> {
2923        Ok(value)
2924    }
2925}
2926
2927#[cfg(feature = "chrono")]
2928impl FromPostgresValue for chrono::DateTime<chrono::FixedOffset> {
2929    impl_from_postgres_value_errors!("DateTime<FixedOffset>");
2930
2931    fn from_postgres_timestamptz(
2932        value: chrono::DateTime<chrono::FixedOffset>,
2933    ) -> Result<Self, DrizzleError> {
2934        Ok(value)
2935    }
2936}
2937
2938#[cfg(feature = "chrono")]
2939impl FromPostgresValue for chrono::DateTime<chrono::Utc> {
2940    impl_from_postgres_value_errors!("DateTime<Utc>");
2941
2942    fn from_postgres_timestamptz(
2943        value: chrono::DateTime<chrono::FixedOffset>,
2944    ) -> Result<Self, DrizzleError> {
2945        Ok(value.with_timezone(&chrono::Utc))
2946    }
2947}
2948
2949#[cfg(feature = "chrono")]
2950impl FromPostgresValue for chrono::Duration {
2951    impl_from_postgres_value_errors!("Duration");
2952
2953    fn from_postgres_interval(value: chrono::Duration) -> Result<Self, DrizzleError> {
2954        Ok(value)
2955    }
2956}
2957
2958// =============================================================================
2959// Time crate support (when feature enabled)
2960// =============================================================================
2961
2962#[cfg(feature = "time")]
2963impl FromPostgresValue for time::Date {
2964    impl_from_postgres_value_errors!("time::Date");
2965
2966    fn from_postgres_time_date(value: time::Date) -> Result<Self, DrizzleError> {
2967        Ok(value)
2968    }
2969}
2970
2971#[cfg(feature = "time")]
2972impl FromPostgresValue for time::Time {
2973    impl_from_postgres_value_errors!("time::Time");
2974
2975    fn from_postgres_time_time(value: time::Time) -> Result<Self, DrizzleError> {
2976        Ok(value)
2977    }
2978}
2979
2980#[cfg(feature = "time")]
2981impl FromPostgresValue for time::PrimitiveDateTime {
2982    impl_from_postgres_value_errors!("time::PrimitiveDateTime");
2983
2984    fn from_postgres_time_timestamp(value: time::PrimitiveDateTime) -> Result<Self, DrizzleError> {
2985        Ok(value)
2986    }
2987}
2988
2989#[cfg(feature = "time")]
2990impl FromPostgresValue for time::OffsetDateTime {
2991    impl_from_postgres_value_errors!("time::OffsetDateTime");
2992
2993    fn from_postgres_time_timestamptz(value: time::OffsetDateTime) -> Result<Self, DrizzleError> {
2994        Ok(value)
2995    }
2996}
2997
2998#[cfg(feature = "time")]
2999impl FromPostgresValue for time::Duration {
3000    impl_from_postgres_value_errors!("time::Duration");
3001
3002    fn from_postgres_time_interval(value: time::Duration) -> Result<Self, DrizzleError> {
3003        Ok(value)
3004    }
3005}
3006
3007#[cfg(feature = "jiff")]
3008impl FromPostgresValue for jiff::civil::Date {
3009    impl_from_postgres_value_errors!("jiff::civil::Date");
3010
3011    fn from_postgres_jiff_date(value: jiff::civil::Date) -> Result<Self, DrizzleError> {
3012        Ok(value)
3013    }
3014}
3015
3016#[cfg(feature = "jiff")]
3017impl FromPostgresValue for jiff::civil::Time {
3018    impl_from_postgres_value_errors!("jiff::civil::Time");
3019
3020    fn from_postgres_jiff_time(value: jiff::civil::Time) -> Result<Self, DrizzleError> {
3021        Ok(value)
3022    }
3023}
3024
3025#[cfg(feature = "jiff")]
3026impl FromPostgresValue for jiff::civil::DateTime {
3027    impl_from_postgres_value_errors!("jiff::civil::DateTime");
3028
3029    fn from_postgres_jiff_datetime(value: jiff::civil::DateTime) -> Result<Self, DrizzleError> {
3030        Ok(value)
3031    }
3032}
3033
3034#[cfg(feature = "jiff")]
3035impl FromPostgresValue for jiff::Timestamp {
3036    impl_from_postgres_value_errors!("jiff::Timestamp");
3037
3038    fn from_postgres_jiff_timestamp(value: jiff::Timestamp) -> Result<Self, DrizzleError> {
3039        Ok(value)
3040    }
3041}
3042
3043// =============================================================================
3044// Network types (when feature enabled)
3045// =============================================================================
3046
3047#[cfg(feature = "cidr")]
3048impl FromPostgresValue for cidr::IpInet {
3049    impl_from_postgres_value_errors!("IpInet");
3050
3051    fn from_postgres_inet(value: cidr::IpInet) -> Result<Self, DrizzleError> {
3052        Ok(value)
3053    }
3054}
3055
3056#[cfg(feature = "cidr")]
3057impl FromPostgresValue for cidr::IpCidr {
3058    impl_from_postgres_value_errors!("IpCidr");
3059
3060    fn from_postgres_cidr(value: cidr::IpCidr) -> Result<Self, DrizzleError> {
3061        Ok(value)
3062    }
3063}
3064
3065#[cfg(feature = "cidr")]
3066impl FromPostgresValue for [u8; 6] {
3067    impl_from_postgres_value_errors!("MACADDR");
3068
3069    fn from_postgres_macaddr(value: [u8; 6]) -> Result<Self, DrizzleError> {
3070        Ok(value)
3071    }
3072}
3073
3074#[cfg(feature = "cidr")]
3075impl FromPostgresValue for [u8; 8] {
3076    impl_from_postgres_value_errors!("MACADDR8");
3077
3078    fn from_postgres_macaddr8(value: [u8; 8]) -> Result<Self, DrizzleError> {
3079        Ok(value)
3080    }
3081}
3082
3083// =============================================================================
3084// Geometric types (when feature enabled)
3085// =============================================================================
3086
3087#[cfg(feature = "geo-types")]
3088impl FromPostgresValue for geo_types::Point<f64> {
3089    impl_from_postgres_value_errors!("Point");
3090
3091    fn from_postgres_point(value: geo_types::Point<f64>) -> Result<Self, DrizzleError> {
3092        Ok(value)
3093    }
3094}
3095
3096#[cfg(feature = "geo-types")]
3097impl FromPostgresValue for geo_types::LineString<f64> {
3098    impl_from_postgres_value_errors!("LineString");
3099
3100    fn from_postgres_linestring(value: geo_types::LineString<f64>) -> Result<Self, DrizzleError> {
3101        Ok(value)
3102    }
3103}
3104
3105#[cfg(feature = "geo-types")]
3106impl FromPostgresValue for geo_types::Rect<f64> {
3107    impl_from_postgres_value_errors!("Rect");
3108
3109    fn from_postgres_rect(value: geo_types::Rect<f64>) -> Result<Self, DrizzleError> {
3110        Ok(value)
3111    }
3112}
3113
3114// =============================================================================
3115// Bit string types (when feature enabled)
3116// =============================================================================
3117
3118#[cfg(feature = "bit-vec")]
3119impl FromPostgresValue for bit_vec::BitVec {
3120    impl_from_postgres_value_errors!("BitVec");
3121
3122    fn from_postgres_bitvec(value: bit_vec::BitVec) -> Result<Self, DrizzleError> {
3123        Ok(value)
3124    }
3125}
3126
3127// =============================================================================
3128// ArrayVec/ArrayString support (when feature enabled)
3129// =============================================================================
3130
3131#[cfg(feature = "arrayvec")]
3132impl<const N: usize> FromPostgresValue for arrayvec::ArrayString<N> {
3133    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3134        let s = value.to_string();
3135        Self::from(&s).map_err(|_| {
3136            DrizzleError::ConversionError(
3137                format!(
3138                    "String length {} exceeds ArrayString capacity {}",
3139                    s.len(),
3140                    N
3141                )
3142                .into(),
3143            )
3144        })
3145    }
3146
3147    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3148        let s = value.to_string();
3149        Self::from(&s).map_err(|_| {
3150            DrizzleError::ConversionError(
3151                format!(
3152                    "String length {} exceeds ArrayString capacity {}",
3153                    s.len(),
3154                    N
3155                )
3156                .into(),
3157            )
3158        })
3159    }
3160
3161    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3162        let s = value.to_string();
3163        Self::from(&s).map_err(|_| {
3164            DrizzleError::ConversionError(
3165                format!(
3166                    "String length {} exceeds ArrayString capacity {}",
3167                    s.len(),
3168                    N
3169                )
3170                .into(),
3171            )
3172        })
3173    }
3174
3175    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3176        let s = value.to_string();
3177        Self::from(&s).map_err(|_| {
3178            DrizzleError::ConversionError(
3179                format!(
3180                    "String length {} exceeds ArrayString capacity {}",
3181                    s.len(),
3182                    N
3183                )
3184                .into(),
3185            )
3186        })
3187    }
3188
3189    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3190        let s = value.to_string();
3191        Self::from(&s).map_err(|_| {
3192            DrizzleError::ConversionError(
3193                format!(
3194                    "String length {} exceeds ArrayString capacity {}",
3195                    s.len(),
3196                    N
3197                )
3198                .into(),
3199            )
3200        })
3201    }
3202
3203    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3204        let s = value.to_string();
3205        Self::from(&s).map_err(|_| {
3206            DrizzleError::ConversionError(
3207                format!(
3208                    "String length {} exceeds ArrayString capacity {}",
3209                    s.len(),
3210                    N
3211                )
3212                .into(),
3213            )
3214        })
3215    }
3216
3217    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3218        Self::from(value).map_err(|_| {
3219            DrizzleError::ConversionError(
3220                format!(
3221                    "Text length {} exceeds ArrayString capacity {}",
3222                    value.len(),
3223                    N
3224                )
3225                .into(),
3226            )
3227        })
3228    }
3229
3230    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3231        let s = String::from_utf8(value.to_vec())
3232            .map_err(|e| DrizzleError::ConversionError(format!("invalid UTF-8: {e}").into()))?;
3233        Self::from(&s).map_err(|_| {
3234            DrizzleError::ConversionError(
3235                format!(
3236                    "String length {} exceeds ArrayString capacity {}",
3237                    s.len(),
3238                    N
3239                )
3240                .into(),
3241            )
3242        })
3243    }
3244}
3245
3246#[cfg(feature = "arrayvec")]
3247impl<const N: usize> FromPostgresValue for arrayvec::ArrayVec<u8, N> {
3248    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
3249        Err(DrizzleError::ConversionError(
3250            "cannot convert bool to ArrayVec<u8>, use BYTEA".into(),
3251        ))
3252    }
3253
3254    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
3255        Err(DrizzleError::ConversionError(
3256            "cannot convert i16 to ArrayVec<u8>, use BYTEA".into(),
3257        ))
3258    }
3259
3260    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
3261        Err(DrizzleError::ConversionError(
3262            "cannot convert i32 to ArrayVec<u8>, use BYTEA".into(),
3263        ))
3264    }
3265
3266    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
3267        Err(DrizzleError::ConversionError(
3268            "cannot convert i64 to ArrayVec<u8>, use BYTEA".into(),
3269        ))
3270    }
3271
3272    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
3273        Err(DrizzleError::ConversionError(
3274            "cannot convert f32 to ArrayVec<u8>, use BYTEA".into(),
3275        ))
3276    }
3277
3278    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
3279        Err(DrizzleError::ConversionError(
3280            "cannot convert f64 to ArrayVec<u8>, use BYTEA".into(),
3281        ))
3282    }
3283
3284    fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
3285        Err(DrizzleError::ConversionError(
3286            "cannot convert TEXT to ArrayVec<u8>, use BYTEA".into(),
3287        ))
3288    }
3289
3290    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3291        Self::try_from(value).map_err(|_| {
3292            DrizzleError::ConversionError(
3293                format!(
3294                    "Bytes length {} exceeds ArrayVec capacity {}",
3295                    value.len(),
3296                    N
3297                )
3298                .into(),
3299            )
3300        })
3301    }
3302}
3303
3304#[cfg(feature = "compact-str")]
3305impl FromPostgresValue for compact_str::CompactString {
3306    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3307        Ok(Self::new(value.to_string()))
3308    }
3309
3310    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3311        Ok(Self::new(value.to_string()))
3312    }
3313
3314    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3315        Ok(Self::new(value.to_string()))
3316    }
3317
3318    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3319        Ok(Self::new(value.to_string()))
3320    }
3321
3322    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3323        Ok(Self::new(value.to_string()))
3324    }
3325
3326    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3327        Ok(Self::new(value.to_string()))
3328    }
3329
3330    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3331        Ok(Self::new(value))
3332    }
3333
3334    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3335        let s = String::from_utf8(value.to_vec()).map_err(|e| {
3336            DrizzleError::ConversionError(format!("invalid UTF-8 in BYTEA: {e}").into())
3337        })?;
3338        Ok(Self::new(s))
3339    }
3340}
3341
3342#[cfg(feature = "bytes")]
3343impl FromPostgresValue for bytes::Bytes {
3344    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3345        Vec::<u8>::from_postgres_bool(value).map(Self::from)
3346    }
3347
3348    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3349        Vec::<u8>::from_postgres_i16(value).map(Self::from)
3350    }
3351
3352    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3353        Vec::<u8>::from_postgres_i32(value).map(Self::from)
3354    }
3355
3356    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3357        Vec::<u8>::from_postgres_i64(value).map(Self::from)
3358    }
3359
3360    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3361        Vec::<u8>::from_postgres_f32(value).map(Self::from)
3362    }
3363
3364    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3365        Vec::<u8>::from_postgres_f64(value).map(Self::from)
3366    }
3367
3368    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3369        Vec::<u8>::from_postgres_text(value).map(Self::from)
3370    }
3371
3372    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3373        Ok(Self::copy_from_slice(value))
3374    }
3375}
3376
3377#[cfg(feature = "bytes")]
3378impl FromPostgresValue for bytes::BytesMut {
3379    fn from_postgres_bool(value: bool) -> Result<Self, DrizzleError> {
3380        Vec::<u8>::from_postgres_bool(value).map(|v| Self::from(v.as_slice()))
3381    }
3382
3383    fn from_postgres_i16(value: i16) -> Result<Self, DrizzleError> {
3384        Vec::<u8>::from_postgres_i16(value).map(|v| Self::from(v.as_slice()))
3385    }
3386
3387    fn from_postgres_i32(value: i32) -> Result<Self, DrizzleError> {
3388        Vec::<u8>::from_postgres_i32(value).map(|v| Self::from(v.as_slice()))
3389    }
3390
3391    fn from_postgres_i64(value: i64) -> Result<Self, DrizzleError> {
3392        Vec::<u8>::from_postgres_i64(value).map(|v| Self::from(v.as_slice()))
3393    }
3394
3395    fn from_postgres_f32(value: f32) -> Result<Self, DrizzleError> {
3396        Vec::<u8>::from_postgres_f32(value).map(|v| Self::from(v.as_slice()))
3397    }
3398
3399    fn from_postgres_f64(value: f64) -> Result<Self, DrizzleError> {
3400        Vec::<u8>::from_postgres_f64(value).map(|v| Self::from(v.as_slice()))
3401    }
3402
3403    fn from_postgres_text(value: &str) -> Result<Self, DrizzleError> {
3404        Vec::<u8>::from_postgres_text(value).map(|v| Self::from(v.as_slice()))
3405    }
3406
3407    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3408        Ok(Self::from(value))
3409    }
3410}
3411
3412#[cfg(feature = "smallvec")]
3413impl<const N: usize> FromPostgresValue for smallvec::SmallVec<[u8; N]> {
3414    fn from_postgres_bool(_value: bool) -> Result<Self, DrizzleError> {
3415        Err(DrizzleError::ConversionError(
3416            "cannot convert bool to SmallVec<u8>, use BYTEA".into(),
3417        ))
3418    }
3419
3420    fn from_postgres_i16(_value: i16) -> Result<Self, DrizzleError> {
3421        Err(DrizzleError::ConversionError(
3422            "cannot convert i16 to SmallVec<u8>, use BYTEA".into(),
3423        ))
3424    }
3425
3426    fn from_postgres_i32(_value: i32) -> Result<Self, DrizzleError> {
3427        Err(DrizzleError::ConversionError(
3428            "cannot convert i32 to SmallVec<u8>, use BYTEA".into(),
3429        ))
3430    }
3431
3432    fn from_postgres_i64(_value: i64) -> Result<Self, DrizzleError> {
3433        Err(DrizzleError::ConversionError(
3434            "cannot convert i64 to SmallVec<u8>, use BYTEA".into(),
3435        ))
3436    }
3437
3438    fn from_postgres_f32(_value: f32) -> Result<Self, DrizzleError> {
3439        Err(DrizzleError::ConversionError(
3440            "cannot convert f32 to SmallVec<u8>, use BYTEA".into(),
3441        ))
3442    }
3443
3444    fn from_postgres_f64(_value: f64) -> Result<Self, DrizzleError> {
3445        Err(DrizzleError::ConversionError(
3446            "cannot convert f64 to SmallVec<u8>, use BYTEA".into(),
3447        ))
3448    }
3449
3450    fn from_postgres_text(_value: &str) -> Result<Self, DrizzleError> {
3451        Err(DrizzleError::ConversionError(
3452            "cannot convert TEXT to SmallVec<u8>, use BYTEA".into(),
3453        ))
3454    }
3455
3456    fn from_postgres_bytes(value: &[u8]) -> Result<Self, DrizzleError> {
3457        let mut out = Self::new();
3458        out.extend_from_slice(value);
3459        Ok(out)
3460    }
3461}