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