1#![warn(clippy::all, rust_2018_idioms, missing_docs)]
185use fallible_iterator::FallibleIterator;
186use postgres_protocol::types::{self, ArrayDimension};
187use std::any::type_name;
188use std::borrow::Cow;
189use std::collections::HashMap;
190use std::error::Error;
191use std::fmt;
192use std::hash::BuildHasher;
193use std::net::IpAddr;
194use std::sync::Arc;
195use std::time::{Duration, SystemTime, UNIX_EPOCH};
196
197#[cfg(feature = "derive")]
198pub use postgres_derive::{FromSql, ToSql};
199
200#[cfg(feature = "with-serde_json-1")]
201pub use crate::serde_json_1::Json;
202use crate::type_gen::{Inner, Other};
203
204#[doc(inline)]
205pub use postgres_protocol::Oid;
206
207#[doc(inline)]
208pub use pg_lsn::PgLsn;
209
210pub use crate::special::{Date, Timestamp};
211use bytes::BytesMut;
212
213const TIME_SEC_CONVERSION: u64 = 946_684_800;
215const USEC_PER_SEC: u64 = 1_000_000;
216const NSEC_PER_USEC: u64 = 1_000;
217
218#[macro_export]
221macro_rules! accepts {
222 ($($expected:ident),+) => (
223 fn accepts(ty: &$crate::Type) -> bool {
224 matches!(*ty, $($crate::Type::$expected)|+)
225 }
226 )
227}
228
229#[macro_export]
233macro_rules! to_sql_checked {
234 () => {
235 fn to_sql_checked(
236 &self,
237 ty: &$crate::Type,
238 out: &mut $crate::private::BytesMut,
239 ) -> ::std::result::Result<
240 $crate::IsNull,
241 Box<dyn ::std::error::Error + ::std::marker::Sync + ::std::marker::Send>,
242 > {
243 $crate::__to_sql_checked(self, ty, out)
244 }
245 };
246}
247
248#[doc(hidden)]
251pub fn __to_sql_checked<T>(
252 v: &T,
253 ty: &Type,
254 out: &mut BytesMut,
255) -> Result<IsNull, Box<dyn Error + Sync + Send>>
256where
257 T: ToSql,
258{
259 if !T::accepts(ty) {
260 return Err(Box::new(WrongType::new::<T>(ty.clone())));
261 }
262 v.to_sql(ty, out)
263}
264
265#[cfg(feature = "with-bit-vec-0_6")]
266mod bit_vec_06;
267#[cfg(feature = "with-bit-vec-0_7")]
268mod bit_vec_07;
269#[cfg(feature = "with-bit-vec-0_8")]
270mod bit_vec_08;
271#[cfg(feature = "with-bit-vec-0_9")]
272mod bit_vec_09;
273#[cfg(feature = "with-chrono-0_4")]
274mod chrono_04;
275#[cfg(feature = "with-cidr-0_2")]
276mod cidr_02;
277#[cfg(feature = "with-cidr-0_3")]
278mod cidr_03;
279#[cfg(feature = "with-eui48-0_4")]
280mod eui48_04;
281#[cfg(feature = "with-eui48-1")]
282mod eui48_1;
283#[cfg(feature = "with-geo-types-0_6")]
284mod geo_types_06;
285#[cfg(feature = "with-geo-types-0_7")]
286mod geo_types_07;
287#[cfg(feature = "with-jiff-0_1")]
288mod jiff_01;
289#[cfg(feature = "with-jiff-0_2")]
290mod jiff_02;
291#[cfg(feature = "with-serde_json-1")]
292mod serde_json_1;
293#[cfg(feature = "with-smol_str-01")]
294mod smol_str_01;
295#[cfg(feature = "with-time-0_2")]
296mod time_02;
297#[cfg(feature = "with-time-0_3")]
298mod time_03;
299#[cfg(feature = "with-uuid-0_8")]
300mod uuid_08;
301#[cfg(feature = "with-uuid-1")]
302mod uuid_1;
303
304#[cfg(feature = "with-time-0_2")]
306extern crate time_02 as time;
307
308mod pg_lsn;
309#[doc(hidden)]
310pub mod private;
311mod special;
312mod type_gen;
313
314#[derive(PartialEq, Eq, Clone, Hash)]
316pub struct Type(Inner);
317
318impl fmt::Debug for Type {
319 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
320 fmt::Debug::fmt(&self.0, fmt)
321 }
322}
323
324impl fmt::Display for Type {
325 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
326 match self.schema() {
327 "public" | "pg_catalog" => {}
328 schema => write!(fmt, "{schema}.")?,
329 }
330 fmt.write_str(self.name())
331 }
332}
333
334impl Type {
335 pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
337 Type(Inner::Other(Arc::new(Other {
338 name,
339 oid,
340 kind,
341 schema,
342 })))
343 }
344
345 pub fn from_oid(oid: Oid) -> Option<Type> {
348 Inner::from_oid(oid).map(Type)
349 }
350
351 pub fn oid(&self) -> Oid {
353 self.0.oid()
354 }
355
356 pub fn kind(&self) -> &Kind {
358 self.0.kind()
359 }
360
361 pub fn schema(&self) -> &str {
363 match self.0 {
364 Inner::Other(ref u) => &u.schema,
365 _ => "pg_catalog",
366 }
367 }
368
369 pub fn name(&self) -> &str {
371 self.0.name()
372 }
373}
374
375#[derive(Debug, Clone, PartialEq, Eq, Hash)]
377#[non_exhaustive]
378pub enum Kind {
379 Simple,
381 Enum(Vec<String>),
383 Pseudo,
385 Array(Type),
387 Range(Type),
389 Multirange(Type),
391 Domain(Type),
393 Composite(Vec<Field>),
395}
396
397#[derive(Debug, Clone, PartialEq, Eq, Hash)]
399pub struct Field {
400 name: String,
401 type_: Type,
402}
403
404impl Field {
405 pub fn new(name: String, type_: Type) -> Field {
407 Field { name, type_ }
408 }
409
410 pub fn name(&self) -> &str {
412 &self.name
413 }
414
415 pub fn type_(&self) -> &Type {
417 &self.type_
418 }
419}
420
421#[derive(Debug, Clone, Copy)]
424pub struct WasNull;
425
426impl fmt::Display for WasNull {
427 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
428 fmt.write_str("a Postgres value was `NULL`")
429 }
430}
431
432impl Error for WasNull {}
433
434#[derive(Debug)]
437pub struct WrongType {
438 postgres: Type,
439 rust: &'static str,
440}
441
442impl fmt::Display for WrongType {
443 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
444 write!(
445 fmt,
446 "cannot convert between the Rust type `{}` and the Postgres type `{}`",
447 self.rust, self.postgres,
448 )
449 }
450}
451
452impl Error for WrongType {}
453
454impl WrongType {
455 pub fn new<T>(ty: Type) -> WrongType {
457 WrongType {
458 postgres: ty,
459 rust: type_name::<T>(),
460 }
461 }
462}
463
464pub trait FromSql<'a>: Sized {
540 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
546
547 #[allow(unused_variables)]
554 fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
555 Err(Box::new(WasNull))
556 }
557
558 fn from_sql_nullable(
561 ty: &Type,
562 raw: Option<&'a [u8]>,
563 ) -> Result<Self, Box<dyn Error + Sync + Send>> {
564 match raw {
565 Some(raw) => Self::from_sql(ty, raw),
566 None => Self::from_sql_null(ty),
567 }
568 }
569
570 fn accepts(ty: &Type) -> bool;
573}
574
575pub trait FromSqlOwned: for<'a> FromSql<'a> {}
579
580impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
581
582impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
583 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
584 <T as FromSql>::from_sql(ty, raw).map(Some)
585 }
586
587 fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
588 Ok(None)
589 }
590
591 fn accepts(ty: &Type) -> bool {
592 <T as FromSql>::accepts(ty)
593 }
594}
595
596impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
597 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
598 let member_type = match *ty.kind() {
599 Kind::Array(ref member) => member,
600 _ => panic!("expected array type"),
601 };
602
603 let array = types::array_from_sql(raw)?;
604 if array.dimensions().count()? > 1 {
605 return Err("array contains too many dimensions".into());
606 }
607
608 array
609 .values()
610 .map(|v| T::from_sql_nullable(member_type, v))
611 .collect()
612 }
613
614 fn accepts(ty: &Type) -> bool {
615 match *ty.kind() {
616 Kind::Array(ref inner) => T::accepts(inner),
617 _ => false,
618 }
619 }
620}
621
622#[cfg(feature = "array-impls")]
623impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
624 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
625 let member_type = match *ty.kind() {
626 Kind::Array(ref member) => member,
627 _ => panic!("expected array type"),
628 };
629
630 let array = types::array_from_sql(raw)?;
631 if array.dimensions().count()? > 1 {
632 return Err("array contains too many dimensions".into());
633 }
634
635 let mut values = array.values();
636 let out = array_init::try_array_init(|i| {
637 let v = values
638 .next()?
639 .ok_or_else(|| -> Box<dyn Error + Sync + Send> {
640 format!("too few elements in array (expected {N}, got {i})").into()
641 })?;
642 T::from_sql_nullable(member_type, v)
643 })?;
644 if values.next()?.is_some() {
645 return Err(
646 format!("excess elements in array (expected {N}, got more than that)",).into(),
647 );
648 }
649
650 Ok(out)
651 }
652
653 fn accepts(ty: &Type) -> bool {
654 match *ty.kind() {
655 Kind::Array(ref inner) => T::accepts(inner),
656 _ => false,
657 }
658 }
659}
660
661impl<'a, T: FromSql<'a>> FromSql<'a> for Box<T> {
662 fn from_sql(ty: &Type, row: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
663 T::from_sql(ty, row).map(Box::new)
664 }
665
666 fn accepts(ty: &Type) -> bool {
667 T::accepts(ty)
668 }
669}
670
671impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
672 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
673 Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
674 }
675
676 fn accepts(ty: &Type) -> bool {
677 Vec::<T>::accepts(ty)
678 }
679}
680
681impl<'a> FromSql<'a> for Vec<u8> {
682 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
683 Ok(types::bytea_from_sql(raw).to_owned())
684 }
685
686 accepts!(BYTEA);
687}
688
689impl<'a> FromSql<'a> for &'a [u8] {
690 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
691 Ok(types::bytea_from_sql(raw))
692 }
693
694 accepts!(BYTEA);
695}
696
697impl<'a> FromSql<'a> for String {
698 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
699 <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
700 }
701
702 fn accepts(ty: &Type) -> bool {
703 <&str as FromSql>::accepts(ty)
704 }
705}
706
707impl<'a> FromSql<'a> for Box<str> {
708 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
709 <&str as FromSql>::from_sql(ty, raw)
710 .map(ToString::to_string)
711 .map(String::into_boxed_str)
712 }
713
714 fn accepts(ty: &Type) -> bool {
715 <&str as FromSql>::accepts(ty)
716 }
717}
718
719impl<'a> FromSql<'a> for &'a str {
720 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
721 match *ty {
722 ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
723 ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
724 ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
725 _ => types::text_from_sql(raw),
726 }
727 }
728
729 fn accepts(ty: &Type) -> bool {
730 match *ty {
731 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
732 ref ty
733 if (ty.name() == "citext"
734 || ty.name() == "ltree"
735 || ty.name() == "lquery"
736 || ty.name() == "ltxtquery") =>
737 {
738 true
739 }
740 _ => false,
741 }
742 }
743}
744
745macro_rules! simple_from {
746 ($t:ty, $f:ident, $($expected:ident),+) => {
747 impl<'a> FromSql<'a> for $t {
748 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
749 types::$f(raw)
750 }
751
752 accepts!($($expected),+);
753 }
754 }
755}
756
757simple_from!(bool, bool_from_sql, BOOL);
758simple_from!(i8, char_from_sql, CHAR);
759simple_from!(i16, int2_from_sql, INT2);
760simple_from!(i32, int4_from_sql, INT4);
761simple_from!(u32, oid_from_sql, OID);
762simple_from!(i64, int8_from_sql, INT8);
763simple_from!(f32, float4_from_sql, FLOAT4);
764simple_from!(f64, float8_from_sql, FLOAT8);
765
766impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
767where
768 S: Default + BuildHasher,
769{
770 fn from_sql(
771 _: &Type,
772 raw: &'a [u8],
773 ) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
774 types::hstore_from_sql(raw)?
775 .map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
776 .collect()
777 }
778
779 fn accepts(ty: &Type) -> bool {
780 ty.name() == "hstore"
781 }
782}
783
784impl<'a> FromSql<'a> for SystemTime {
785 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
786 let time = types::timestamp_from_sql(raw)?;
787 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
788
789 let negative = time < 0;
790 let time = time.unsigned_abs();
791
792 let secs = time / USEC_PER_SEC;
793 let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
794 let offset = Duration::new(secs, nsec as u32);
795
796 let time = if negative {
797 epoch - offset
798 } else {
799 epoch + offset
800 };
801
802 Ok(time)
803 }
804
805 accepts!(TIMESTAMP, TIMESTAMPTZ);
806}
807
808impl<'a> FromSql<'a> for IpAddr {
809 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
810 let inet = types::inet_from_sql(raw)?;
811 Ok(inet.addr())
812 }
813
814 accepts!(INET);
815}
816
817pub enum IsNull {
819 Yes,
821 No,
823}
824
825pub trait ToSql: fmt::Debug {
896 fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
906 where
907 Self: Sized;
908
909 fn accepts(ty: &Type) -> bool
912 where
913 Self: Sized;
914
915 fn to_sql_checked(
920 &self,
921 ty: &Type,
922 out: &mut BytesMut,
923 ) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
924
925 fn encode_format(&self, _ty: &Type) -> Format {
927 Format::Binary
928 }
929}
930
931#[derive(Clone, Copy, Debug)]
935pub enum Format {
936 Text,
938 Binary,
940}
941
942impl<T> ToSql for &T
943where
944 T: ToSql,
945{
946 fn to_sql(
947 &self,
948 ty: &Type,
949 out: &mut BytesMut,
950 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
951 (*self).to_sql(ty, out)
952 }
953
954 fn accepts(ty: &Type) -> bool {
955 T::accepts(ty)
956 }
957
958 fn encode_format(&self, ty: &Type) -> Format {
959 (*self).encode_format(ty)
960 }
961
962 to_sql_checked!();
963}
964
965impl<T: ToSql> ToSql for Option<T> {
966 fn to_sql(
967 &self,
968 ty: &Type,
969 out: &mut BytesMut,
970 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
971 match *self {
972 Some(ref val) => val.to_sql(ty, out),
973 None => Ok(IsNull::Yes),
974 }
975 }
976
977 fn accepts(ty: &Type) -> bool {
978 <T as ToSql>::accepts(ty)
979 }
980
981 fn encode_format(&self, ty: &Type) -> Format {
982 match self {
983 Some(val) => val.encode_format(ty),
984 None => Format::Binary,
985 }
986 }
987
988 to_sql_checked!();
989}
990
991impl<T: ToSql> ToSql for &[T] {
992 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
993 let member_type = match *ty.kind() {
994 Kind::Array(ref member) => member,
995 _ => panic!("expected array type"),
996 };
997
998 let lower_bound = match *ty {
1000 Type::OID_VECTOR | Type::INT2_VECTOR => 0,
1001 _ => 1,
1002 };
1003
1004 let dimension = ArrayDimension {
1005 len: downcast(self.len())?,
1006 lower_bound,
1007 };
1008
1009 types::array_to_sql(
1010 Some(dimension),
1011 member_type.oid(),
1012 self.iter(),
1013 |e, w| match e.to_sql(member_type, w)? {
1014 IsNull::No => Ok(postgres_protocol::IsNull::No),
1015 IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
1016 },
1017 w,
1018 )?;
1019 Ok(IsNull::No)
1020 }
1021
1022 fn accepts(ty: &Type) -> bool {
1023 match *ty.kind() {
1024 Kind::Array(ref member) => T::accepts(member),
1025 _ => false,
1026 }
1027 }
1028
1029 to_sql_checked!();
1030}
1031
1032impl ToSql for &[u8] {
1033 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1034 types::bytea_to_sql(self, w);
1035 Ok(IsNull::No)
1036 }
1037
1038 accepts!(BYTEA);
1039
1040 to_sql_checked!();
1041}
1042
1043#[cfg(feature = "array-impls")]
1044impl<const N: usize> ToSql for [u8; N] {
1045 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1046 types::bytea_to_sql(&self[..], w);
1047 Ok(IsNull::No)
1048 }
1049
1050 accepts!(BYTEA);
1051
1052 to_sql_checked!();
1053}
1054
1055#[cfg(feature = "array-impls")]
1056impl<T: ToSql, const N: usize> ToSql for [T; N] {
1057 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1058 <&[T] as ToSql>::to_sql(&&self[..], ty, w)
1059 }
1060
1061 fn accepts(ty: &Type) -> bool {
1062 <&[T] as ToSql>::accepts(ty)
1063 }
1064
1065 to_sql_checked!();
1066}
1067
1068impl<T: ToSql> ToSql for Vec<T> {
1069 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1070 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1071 }
1072
1073 fn accepts(ty: &Type) -> bool {
1074 <&[T] as ToSql>::accepts(ty)
1075 }
1076
1077 to_sql_checked!();
1078}
1079
1080impl<T: ToSql> ToSql for Box<T> {
1081 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1082 <&T as ToSql>::to_sql(&&**self, ty, w)
1083 }
1084
1085 fn accepts(ty: &Type) -> bool {
1086 <&T as ToSql>::accepts(ty)
1087 }
1088
1089 to_sql_checked!();
1090}
1091
1092impl<T: ToSql> ToSql for Box<[T]> {
1093 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1094 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1095 }
1096
1097 fn accepts(ty: &Type) -> bool {
1098 <&[T] as ToSql>::accepts(ty)
1099 }
1100
1101 to_sql_checked!();
1102}
1103
1104impl ToSql for Cow<'_, [u8]> {
1105 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1106 <&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
1107 }
1108
1109 fn accepts(ty: &Type) -> bool {
1110 <&[u8] as ToSql>::accepts(ty)
1111 }
1112
1113 to_sql_checked!();
1114}
1115
1116impl ToSql for Vec<u8> {
1117 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1118 <&[u8] as ToSql>::to_sql(&&**self, ty, w)
1119 }
1120
1121 fn accepts(ty: &Type) -> bool {
1122 <&[u8] as ToSql>::accepts(ty)
1123 }
1124
1125 to_sql_checked!();
1126}
1127
1128impl ToSql for &str {
1129 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1130 match ty.name() {
1131 "ltree" => types::ltree_to_sql(self, w),
1132 "lquery" => types::lquery_to_sql(self, w),
1133 "ltxtquery" => types::ltxtquery_to_sql(self, w),
1134 _ => types::text_to_sql(self, w),
1135 }
1136 Ok(IsNull::No)
1137 }
1138
1139 fn accepts(ty: &Type) -> bool {
1140 matches!(
1141 *ty,
1142 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
1143 ) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
1144 }
1145
1146 to_sql_checked!();
1147}
1148
1149impl ToSql for Cow<'_, str> {
1150 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1151 <&str as ToSql>::to_sql(&self.as_ref(), ty, w)
1152 }
1153
1154 fn accepts(ty: &Type) -> bool {
1155 <&str as ToSql>::accepts(ty)
1156 }
1157
1158 to_sql_checked!();
1159}
1160
1161impl ToSql for String {
1162 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1163 <&str as ToSql>::to_sql(&&**self, ty, w)
1164 }
1165
1166 fn accepts(ty: &Type) -> bool {
1167 <&str as ToSql>::accepts(ty)
1168 }
1169
1170 to_sql_checked!();
1171}
1172
1173impl ToSql for Box<str> {
1174 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1175 <&str as ToSql>::to_sql(&&**self, ty, w)
1176 }
1177
1178 fn accepts(ty: &Type) -> bool {
1179 <&str as ToSql>::accepts(ty)
1180 }
1181
1182 to_sql_checked!();
1183}
1184
1185macro_rules! simple_to {
1186 ($t:ty, $f:ident, $($expected:ident),+) => {
1187 impl ToSql for $t {
1188 fn to_sql(&self,
1189 _: &Type,
1190 w: &mut BytesMut)
1191 -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1192 types::$f(*self, w);
1193 Ok(IsNull::No)
1194 }
1195
1196 accepts!($($expected),+);
1197
1198 to_sql_checked!();
1199 }
1200 }
1201}
1202
1203simple_to!(bool, bool_to_sql, BOOL);
1204simple_to!(i8, char_to_sql, CHAR);
1205simple_to!(i16, int2_to_sql, INT2);
1206simple_to!(i32, int4_to_sql, INT4);
1207simple_to!(u32, oid_to_sql, OID);
1208simple_to!(i64, int8_to_sql, INT8);
1209simple_to!(f32, float4_to_sql, FLOAT4);
1210simple_to!(f64, float8_to_sql, FLOAT8);
1211
1212impl<H> ToSql for HashMap<String, Option<String>, H>
1213where
1214 H: BuildHasher,
1215{
1216 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1217 types::hstore_to_sql(
1218 self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
1219 w,
1220 )?;
1221 Ok(IsNull::No)
1222 }
1223
1224 fn accepts(ty: &Type) -> bool {
1225 ty.name() == "hstore"
1226 }
1227
1228 to_sql_checked!();
1229}
1230
1231impl ToSql for SystemTime {
1232 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1233 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
1234
1235 let to_usec =
1236 |d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
1237
1238 let time = match self.duration_since(epoch) {
1239 Ok(duration) => to_usec(duration) as i64,
1240 Err(e) => -(to_usec(e.duration()) as i64),
1241 };
1242
1243 types::timestamp_to_sql(time, w);
1244 Ok(IsNull::No)
1245 }
1246
1247 accepts!(TIMESTAMP, TIMESTAMPTZ);
1248
1249 to_sql_checked!();
1250}
1251
1252impl ToSql for IpAddr {
1253 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1254 let netmask = match self {
1255 IpAddr::V4(_) => 32,
1256 IpAddr::V6(_) => 128,
1257 };
1258 types::inet_to_sql(*self, netmask, w);
1259 Ok(IsNull::No)
1260 }
1261
1262 accepts!(INET);
1263
1264 to_sql_checked!();
1265}
1266
1267fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
1268 if len > i32::MAX as usize {
1269 Err("value too large to transmit".into())
1270 } else {
1271 Ok(len as i32)
1272 }
1273}
1274
1275mod sealed {
1276 pub trait Sealed {}
1277}
1278
1279pub trait BorrowToSql: sealed::Sealed {
1283 fn borrow_to_sql(&self) -> &dyn ToSql;
1285}
1286
1287impl sealed::Sealed for &dyn ToSql {}
1288
1289impl BorrowToSql for &dyn ToSql {
1290 #[inline]
1291 fn borrow_to_sql(&self) -> &dyn ToSql {
1292 *self
1293 }
1294}
1295
1296impl sealed::Sealed for Box<dyn ToSql + Sync + '_> {}
1297
1298impl BorrowToSql for Box<dyn ToSql + Sync + '_> {
1299 #[inline]
1300 fn borrow_to_sql(&self) -> &dyn ToSql {
1301 self.as_ref()
1302 }
1303}
1304
1305impl sealed::Sealed for Box<dyn ToSql + Sync + Send + '_> {}
1306impl BorrowToSql for Box<dyn ToSql + Sync + Send + '_> {
1307 #[inline]
1308 fn borrow_to_sql(&self) -> &dyn ToSql {
1309 self.as_ref()
1310 }
1311}
1312
1313impl sealed::Sealed for &(dyn ToSql + Sync) {}
1314
1315impl BorrowToSql for &(dyn ToSql + Sync) {
1320 #[inline]
1321 fn borrow_to_sql(&self) -> &dyn ToSql {
1322 *self
1323 }
1324}
1325
1326impl<T> sealed::Sealed for T where T: ToSql {}
1327
1328impl<T> BorrowToSql for T
1329where
1330 T: ToSql,
1331{
1332 #[inline]
1333 fn borrow_to_sql(&self) -> &dyn ToSql {
1334 self
1335 }
1336}