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-chrono-0_4")]
268mod chrono_04;
269#[cfg(feature = "with-cidr-0_2")]
270mod cidr_02;
271#[cfg(feature = "with-eui48-0_4")]
272mod eui48_04;
273#[cfg(feature = "with-eui48-1")]
274mod eui48_1;
275#[cfg(feature = "with-geo-types-0_6")]
276mod geo_types_06;
277#[cfg(feature = "with-geo-types-0_7")]
278mod geo_types_07;
279#[cfg(feature = "with-serde_json-1")]
280mod serde_json_1;
281#[cfg(feature = "with-smol_str-01")]
282mod smol_str_01;
283#[cfg(feature = "with-time-0_2")]
284mod time_02;
285#[cfg(feature = "with-time-0_3")]
286mod time_03;
287#[cfg(feature = "with-uuid-0_8")]
288mod uuid_08;
289#[cfg(feature = "with-uuid-1")]
290mod uuid_1;
291
292#[cfg(feature = "with-time-0_2")]
294extern crate time_02 as time;
295
296mod pg_lsn;
297#[doc(hidden)]
298pub mod private;
299mod special;
300mod type_gen;
301
302#[derive(PartialEq, Eq, Clone, Hash)]
304pub struct Type(Inner);
305
306impl fmt::Debug for Type {
307 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
308 fmt::Debug::fmt(&self.0, fmt)
309 }
310}
311
312impl fmt::Display for Type {
313 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
314 match self.schema() {
315 "public" | "pg_catalog" => {}
316 schema => write!(fmt, "{}.", schema)?,
317 }
318 fmt.write_str(self.name())
319 }
320}
321
322impl Type {
323 pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
325 Type(Inner::Other(Arc::new(Other {
326 name,
327 oid,
328 kind,
329 schema,
330 })))
331 }
332
333 pub fn from_oid(oid: Oid) -> Option<Type> {
336 Inner::from_oid(oid).map(Type)
337 }
338
339 pub fn oid(&self) -> Oid {
341 self.0.oid()
342 }
343
344 pub fn kind(&self) -> &Kind {
346 self.0.kind()
347 }
348
349 pub fn schema(&self) -> &str {
351 match self.0 {
352 Inner::Other(ref u) => &u.schema,
353 _ => "pg_catalog",
354 }
355 }
356
357 pub fn name(&self) -> &str {
359 self.0.name()
360 }
361}
362
363#[derive(Debug, Clone, PartialEq, Eq, Hash)]
365#[non_exhaustive]
366pub enum Kind {
367 Simple,
369 Enum(Vec<String>),
371 Pseudo,
373 Array(Type),
375 Range(Type),
377 Multirange(Type),
379 Domain(Type),
381 Composite(Vec<Field>),
383}
384
385#[derive(Debug, Clone, PartialEq, Eq, Hash)]
387pub struct Field {
388 name: String,
389 type_: Type,
390}
391
392impl Field {
393 pub fn new(name: String, type_: Type) -> Field {
395 Field { name, type_ }
396 }
397
398 pub fn name(&self) -> &str {
400 &self.name
401 }
402
403 pub fn type_(&self) -> &Type {
405 &self.type_
406 }
407}
408
409#[derive(Debug, Clone, Copy)]
412pub struct WasNull;
413
414impl fmt::Display for WasNull {
415 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
416 fmt.write_str("a Postgres value was `NULL`")
417 }
418}
419
420impl Error for WasNull {}
421
422#[derive(Debug)]
425pub struct WrongType {
426 postgres: Type,
427 rust: &'static str,
428}
429
430impl fmt::Display for WrongType {
431 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
432 write!(
433 fmt,
434 "cannot convert between the Rust type `{}` and the Postgres type `{}`",
435 self.rust, self.postgres,
436 )
437 }
438}
439
440impl Error for WrongType {}
441
442impl WrongType {
443 pub fn new<T>(ty: Type) -> WrongType {
445 WrongType {
446 postgres: ty,
447 rust: type_name::<T>(),
448 }
449 }
450}
451
452pub trait FromSql<'a>: Sized {
522 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
528
529 #[allow(unused_variables)]
536 fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
537 Err(Box::new(WasNull))
538 }
539
540 fn from_sql_nullable(
543 ty: &Type,
544 raw: Option<&'a [u8]>,
545 ) -> Result<Self, Box<dyn Error + Sync + Send>> {
546 match raw {
547 Some(raw) => Self::from_sql(ty, raw),
548 None => Self::from_sql_null(ty),
549 }
550 }
551
552 fn accepts(ty: &Type) -> bool;
555}
556
557pub trait FromSqlOwned: for<'a> FromSql<'a> {}
561
562impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
563
564impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
565 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
566 <T as FromSql>::from_sql(ty, raw).map(Some)
567 }
568
569 fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
570 Ok(None)
571 }
572
573 fn accepts(ty: &Type) -> bool {
574 <T as FromSql>::accepts(ty)
575 }
576}
577
578impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
579 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
580 let member_type = match *ty.kind() {
581 Kind::Array(ref member) => member,
582 _ => panic!("expected array type"),
583 };
584
585 let array = types::array_from_sql(raw)?;
586 if array.dimensions().count()? > 1 {
587 return Err("array contains too many dimensions".into());
588 }
589
590 array
591 .values()
592 .map(|v| T::from_sql_nullable(member_type, v))
593 .collect()
594 }
595
596 fn accepts(ty: &Type) -> bool {
597 match *ty.kind() {
598 Kind::Array(ref inner) => T::accepts(inner),
599 _ => false,
600 }
601 }
602}
603
604#[cfg(feature = "array-impls")]
605impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
606 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
607 let member_type = match *ty.kind() {
608 Kind::Array(ref member) => member,
609 _ => panic!("expected array type"),
610 };
611
612 let array = types::array_from_sql(raw)?;
613 if array.dimensions().count()? > 1 {
614 return Err("array contains too many dimensions".into());
615 }
616
617 let mut values = array.values();
618 let out = array_init::try_array_init(|i| {
619 let v = values
620 .next()?
621 .ok_or_else(|| -> Box<dyn Error + Sync + Send> {
622 format!("too few elements in array (expected {}, got {})", N, i).into()
623 })?;
624 T::from_sql_nullable(member_type, v)
625 })?;
626 if values.next()?.is_some() {
627 return Err(format!(
628 "excess elements in array (expected {}, got more than that)",
629 N,
630 )
631 .into());
632 }
633
634 Ok(out)
635 }
636
637 fn accepts(ty: &Type) -> bool {
638 match *ty.kind() {
639 Kind::Array(ref inner) => T::accepts(inner),
640 _ => false,
641 }
642 }
643}
644
645impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
646 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
647 Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
648 }
649
650 fn accepts(ty: &Type) -> bool {
651 Vec::<T>::accepts(ty)
652 }
653}
654
655impl<'a> FromSql<'a> for Vec<u8> {
656 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
657 Ok(types::bytea_from_sql(raw).to_owned())
658 }
659
660 accepts!(BYTEA);
661}
662
663impl<'a> FromSql<'a> for &'a [u8] {
664 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
665 Ok(types::bytea_from_sql(raw))
666 }
667
668 accepts!(BYTEA);
669}
670
671impl<'a> FromSql<'a> for String {
672 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
673 <&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
674 }
675
676 fn accepts(ty: &Type) -> bool {
677 <&str as FromSql>::accepts(ty)
678 }
679}
680
681impl<'a> FromSql<'a> for Box<str> {
682 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
683 <&str as FromSql>::from_sql(ty, raw)
684 .map(ToString::to_string)
685 .map(String::into_boxed_str)
686 }
687
688 fn accepts(ty: &Type) -> bool {
689 <&str as FromSql>::accepts(ty)
690 }
691}
692
693impl<'a> FromSql<'a> for &'a str {
694 fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
695 match *ty {
696 ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
697 ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
698 ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
699 _ => types::text_from_sql(raw),
700 }
701 }
702
703 fn accepts(ty: &Type) -> bool {
704 match *ty {
705 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
706 ref ty
707 if (ty.name() == "citext"
708 || ty.name() == "ltree"
709 || ty.name() == "lquery"
710 || ty.name() == "ltxtquery") =>
711 {
712 true
713 }
714 _ => false,
715 }
716 }
717}
718
719macro_rules! simple_from {
720 ($t:ty, $f:ident, $($expected:ident),+) => {
721 impl<'a> FromSql<'a> for $t {
722 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
723 types::$f(raw)
724 }
725
726 accepts!($($expected),+);
727 }
728 }
729}
730
731simple_from!(bool, bool_from_sql, BOOL);
732simple_from!(i8, char_from_sql, CHAR);
733simple_from!(i16, int2_from_sql, INT2);
734simple_from!(i32, int4_from_sql, INT4);
735simple_from!(u32, oid_from_sql, OID);
736simple_from!(i64, int8_from_sql, INT8);
737simple_from!(f32, float4_from_sql, FLOAT4);
738simple_from!(f64, float8_from_sql, FLOAT8);
739
740impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
741where
742 S: Default + BuildHasher,
743{
744 fn from_sql(
745 _: &Type,
746 raw: &'a [u8],
747 ) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
748 types::hstore_from_sql(raw)?
749 .map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
750 .collect()
751 }
752
753 fn accepts(ty: &Type) -> bool {
754 ty.name() == "hstore"
755 }
756}
757
758impl<'a> FromSql<'a> for SystemTime {
759 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
760 let time = types::timestamp_from_sql(raw)?;
761 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
762
763 let negative = time < 0;
764 let time = time.unsigned_abs();
765
766 let secs = time / USEC_PER_SEC;
767 let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
768 let offset = Duration::new(secs, nsec as u32);
769
770 let time = if negative {
771 epoch - offset
772 } else {
773 epoch + offset
774 };
775
776 Ok(time)
777 }
778
779 accepts!(TIMESTAMP, TIMESTAMPTZ);
780}
781
782impl<'a> FromSql<'a> for IpAddr {
783 fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
784 let inet = types::inet_from_sql(raw)?;
785 Ok(inet.addr())
786 }
787
788 accepts!(INET);
789}
790
791pub enum IsNull {
793 Yes,
795 No,
797}
798
799pub trait ToSql: fmt::Debug {
865 fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
875 where
876 Self: Sized;
877
878 fn accepts(ty: &Type) -> bool
881 where
882 Self: Sized;
883
884 fn to_sql_checked(
889 &self,
890 ty: &Type,
891 out: &mut BytesMut,
892 ) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
893
894 fn encode_format(&self, _ty: &Type) -> Format {
896 Format::Binary
897 }
898}
899
900#[derive(Clone, Copy, Debug)]
904pub enum Format {
905 Text,
907 Binary,
909}
910
911impl<'a, T> ToSql for &'a T
912where
913 T: ToSql,
914{
915 fn to_sql(
916 &self,
917 ty: &Type,
918 out: &mut BytesMut,
919 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
920 (*self).to_sql(ty, out)
921 }
922
923 fn accepts(ty: &Type) -> bool {
924 T::accepts(ty)
925 }
926
927 fn encode_format(&self, ty: &Type) -> Format {
928 (*self).encode_format(ty)
929 }
930
931 to_sql_checked!();
932}
933
934impl<T: ToSql> ToSql for Option<T> {
935 fn to_sql(
936 &self,
937 ty: &Type,
938 out: &mut BytesMut,
939 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
940 match *self {
941 Some(ref val) => val.to_sql(ty, out),
942 None => Ok(IsNull::Yes),
943 }
944 }
945
946 fn accepts(ty: &Type) -> bool {
947 <T as ToSql>::accepts(ty)
948 }
949
950 fn encode_format(&self, ty: &Type) -> Format {
951 match self {
952 Some(ref val) => val.encode_format(ty),
953 None => Format::Binary,
954 }
955 }
956
957 to_sql_checked!();
958}
959
960impl<'a, T: ToSql> ToSql for &'a [T] {
961 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
962 let member_type = match *ty.kind() {
963 Kind::Array(ref member) => member,
964 _ => panic!("expected array type"),
965 };
966
967 let lower_bound = match *ty {
969 Type::OID_VECTOR | Type::INT2_VECTOR => 0,
970 _ => 1,
971 };
972
973 let dimension = ArrayDimension {
974 len: downcast(self.len())?,
975 lower_bound,
976 };
977
978 types::array_to_sql(
979 Some(dimension),
980 member_type.oid(),
981 self.iter(),
982 |e, w| match e.to_sql(member_type, w)? {
983 IsNull::No => Ok(postgres_protocol::IsNull::No),
984 IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
985 },
986 w,
987 )?;
988 Ok(IsNull::No)
989 }
990
991 fn accepts(ty: &Type) -> bool {
992 match *ty.kind() {
993 Kind::Array(ref member) => T::accepts(member),
994 _ => false,
995 }
996 }
997
998 to_sql_checked!();
999}
1000
1001impl<'a> ToSql for &'a [u8] {
1002 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1003 types::bytea_to_sql(self, w);
1004 Ok(IsNull::No)
1005 }
1006
1007 accepts!(BYTEA);
1008
1009 to_sql_checked!();
1010}
1011
1012#[cfg(feature = "array-impls")]
1013impl<const N: usize> ToSql for [u8; N] {
1014 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1015 types::bytea_to_sql(&self[..], w);
1016 Ok(IsNull::No)
1017 }
1018
1019 accepts!(BYTEA);
1020
1021 to_sql_checked!();
1022}
1023
1024#[cfg(feature = "array-impls")]
1025impl<T: ToSql, const N: usize> ToSql for [T; N] {
1026 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1027 <&[T] as ToSql>::to_sql(&&self[..], ty, w)
1028 }
1029
1030 fn accepts(ty: &Type) -> bool {
1031 <&[T] as ToSql>::accepts(ty)
1032 }
1033
1034 to_sql_checked!();
1035}
1036
1037impl<T: ToSql> ToSql for Vec<T> {
1038 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1039 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1040 }
1041
1042 fn accepts(ty: &Type) -> bool {
1043 <&[T] as ToSql>::accepts(ty)
1044 }
1045
1046 to_sql_checked!();
1047}
1048
1049impl<T: ToSql> ToSql for Box<[T]> {
1050 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1051 <&[T] as ToSql>::to_sql(&&**self, ty, w)
1052 }
1053
1054 fn accepts(ty: &Type) -> bool {
1055 <&[T] as ToSql>::accepts(ty)
1056 }
1057
1058 to_sql_checked!();
1059}
1060
1061impl<'a> ToSql for Cow<'a, [u8]> {
1062 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1063 <&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
1064 }
1065
1066 fn accepts(ty: &Type) -> bool {
1067 <&[u8] as ToSql>::accepts(ty)
1068 }
1069
1070 to_sql_checked!();
1071}
1072
1073impl ToSql for Vec<u8> {
1074 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1075 <&[u8] as ToSql>::to_sql(&&**self, ty, w)
1076 }
1077
1078 fn accepts(ty: &Type) -> bool {
1079 <&[u8] as ToSql>::accepts(ty)
1080 }
1081
1082 to_sql_checked!();
1083}
1084
1085impl<'a> ToSql for &'a str {
1086 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1087 match ty.name() {
1088 "ltree" => types::ltree_to_sql(self, w),
1089 "lquery" => types::lquery_to_sql(self, w),
1090 "ltxtquery" => types::ltxtquery_to_sql(self, w),
1091 _ => types::text_to_sql(self, w),
1092 }
1093 Ok(IsNull::No)
1094 }
1095
1096 fn accepts(ty: &Type) -> bool {
1097 matches!(
1098 *ty,
1099 Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
1100 ) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
1101 }
1102
1103 to_sql_checked!();
1104}
1105
1106impl<'a> ToSql for Cow<'a, str> {
1107 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1108 <&str as ToSql>::to_sql(&self.as_ref(), ty, w)
1109 }
1110
1111 fn accepts(ty: &Type) -> bool {
1112 <&str as ToSql>::accepts(ty)
1113 }
1114
1115 to_sql_checked!();
1116}
1117
1118impl ToSql for String {
1119 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1120 <&str as ToSql>::to_sql(&&**self, ty, w)
1121 }
1122
1123 fn accepts(ty: &Type) -> bool {
1124 <&str as ToSql>::accepts(ty)
1125 }
1126
1127 to_sql_checked!();
1128}
1129
1130impl ToSql for Box<str> {
1131 fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1132 <&str as ToSql>::to_sql(&&**self, ty, w)
1133 }
1134
1135 fn accepts(ty: &Type) -> bool {
1136 <&str as ToSql>::accepts(ty)
1137 }
1138
1139 to_sql_checked!();
1140}
1141
1142macro_rules! simple_to {
1143 ($t:ty, $f:ident, $($expected:ident),+) => {
1144 impl ToSql for $t {
1145 fn to_sql(&self,
1146 _: &Type,
1147 w: &mut BytesMut)
1148 -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1149 types::$f(*self, w);
1150 Ok(IsNull::No)
1151 }
1152
1153 accepts!($($expected),+);
1154
1155 to_sql_checked!();
1156 }
1157 }
1158}
1159
1160simple_to!(bool, bool_to_sql, BOOL);
1161simple_to!(i8, char_to_sql, CHAR);
1162simple_to!(i16, int2_to_sql, INT2);
1163simple_to!(i32, int4_to_sql, INT4);
1164simple_to!(u32, oid_to_sql, OID);
1165simple_to!(i64, int8_to_sql, INT8);
1166simple_to!(f32, float4_to_sql, FLOAT4);
1167simple_to!(f64, float8_to_sql, FLOAT8);
1168
1169impl<H> ToSql for HashMap<String, Option<String>, H>
1170where
1171 H: BuildHasher,
1172{
1173 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1174 types::hstore_to_sql(
1175 self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
1176 w,
1177 )?;
1178 Ok(IsNull::No)
1179 }
1180
1181 fn accepts(ty: &Type) -> bool {
1182 ty.name() == "hstore"
1183 }
1184
1185 to_sql_checked!();
1186}
1187
1188impl ToSql for SystemTime {
1189 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1190 let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
1191
1192 let to_usec =
1193 |d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
1194
1195 let time = match self.duration_since(epoch) {
1196 Ok(duration) => to_usec(duration) as i64,
1197 Err(e) => -(to_usec(e.duration()) as i64),
1198 };
1199
1200 types::timestamp_to_sql(time, w);
1201 Ok(IsNull::No)
1202 }
1203
1204 accepts!(TIMESTAMP, TIMESTAMPTZ);
1205
1206 to_sql_checked!();
1207}
1208
1209impl ToSql for IpAddr {
1210 fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
1211 let netmask = match self {
1212 IpAddr::V4(_) => 32,
1213 IpAddr::V6(_) => 128,
1214 };
1215 types::inet_to_sql(*self, netmask, w);
1216 Ok(IsNull::No)
1217 }
1218
1219 accepts!(INET);
1220
1221 to_sql_checked!();
1222}
1223
1224fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
1225 if len > i32::MAX as usize {
1226 Err("value too large to transmit".into())
1227 } else {
1228 Ok(len as i32)
1229 }
1230}
1231
1232mod sealed {
1233 pub trait Sealed {}
1234}
1235
1236pub trait BorrowToSql: sealed::Sealed {
1240 fn borrow_to_sql(&self) -> &dyn ToSql;
1242}
1243
1244impl sealed::Sealed for &dyn ToSql {}
1245
1246impl BorrowToSql for &dyn ToSql {
1247 #[inline]
1248 fn borrow_to_sql(&self) -> &dyn ToSql {
1249 *self
1250 }
1251}
1252
1253impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + 'a> {}
1254
1255impl<'a> BorrowToSql for Box<dyn ToSql + Sync + 'a> {
1256 #[inline]
1257 fn borrow_to_sql(&self) -> &dyn ToSql {
1258 self.as_ref()
1259 }
1260}
1261
1262impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + Send + 'a> {}
1263impl<'a> BorrowToSql for Box<dyn ToSql + Sync + Send + 'a> {
1264 #[inline]
1265 fn borrow_to_sql(&self) -> &dyn ToSql {
1266 self.as_ref()
1267 }
1268}
1269
1270impl sealed::Sealed for &(dyn ToSql + Sync) {}
1271
1272impl BorrowToSql for &(dyn ToSql + Sync) {
1277 #[inline]
1278 fn borrow_to_sql(&self) -> &dyn ToSql {
1279 *self
1280 }
1281}
1282
1283impl<T> sealed::Sealed for T where T: ToSql {}
1284
1285impl<T> BorrowToSql for T
1286where
1287 T: ToSql,
1288{
1289 #[inline]
1290 fn borrow_to_sql(&self) -> &dyn ToSql {
1291 self
1292 }
1293}