#![doc(html_root_url = "https://docs.rs/postgres-types/0.2")]
#![warn(clippy::all, rust_2018_idioms, missing_docs)]
use std::{
any::type_name,
borrow::Cow,
collections::HashMap,
convert::TryInto,
error::Error,
fmt,
hash::BuildHasher,
net::IpAddr,
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use bytes::{BufMut, BytesMut};
use fallible_iterator::FallibleIterator;
#[doc(inline)]
pub use pg_lsn::PgLsn;
#[cfg(feature = "derive")]
pub use postgres_derive::{FromSql, ToSql};
use postgres_protocol::types::{self, ArrayDimension};
#[doc(inline)]
pub use postgres_protocol::Oid;
#[cfg(feature = "with-serde_json-1")]
pub use crate::serde_json_1::Json;
pub use crate::special::{Date, Timestamp};
use crate::type_gen::{Inner, Other};
const TIME_SEC_CONVERSION: u64 = 946_684_800;
const USEC_PER_SEC: u64 = 1_000_000;
const NSEC_PER_USEC: u64 = 1_000;
#[macro_export]
macro_rules! accepts {
($($expected:ident),+) => (
fn accepts(ty: &$crate::Type) -> bool {
matches!(*ty, $($crate::Type::$expected)|+)
}
)
}
#[macro_export]
macro_rules! to_sql_checked {
() => {
fn to_sql_checked(
&self,
ty: &$crate::Type,
out: &mut $crate::private::BytesMut,
) -> ::std::result::Result<
$crate::IsNull,
Box<dyn ::std::error::Error + ::std::marker::Sync + ::std::marker::Send>,
> {
$crate::__to_sql_checked(self, ty, out)
}
};
}
#[doc(hidden)]
pub fn __to_sql_checked<T>(
v: &T,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>>
where
T: ToSql,
{
if !T::accepts(ty) {
return Err(Box::new(WrongType::new::<T>(ty.clone())));
}
v.to_sql(ty, out)
}
#[cfg(feature = "with-bit-vec-0_6")]
mod bit_vec_06;
#[cfg(feature = "with-chrono-0_4")]
mod chrono_04;
#[cfg(feature = "with-cidr-0_2")]
mod cidr_02;
#[cfg(feature = "with-eui48-0_4")]
mod eui48_04;
#[cfg(feature = "with-eui48-1")]
mod eui48_1;
#[cfg(feature = "with-geo-types-0_6")]
mod geo_types_06;
#[cfg(feature = "with-geo-types-0_7")]
mod geo_types_07;
#[cfg(feature = "with-serde_json-1")]
mod serde_json_1;
#[cfg(feature = "with-smol_str-01")]
mod smol_str_01;
#[cfg(feature = "with-time-0_2")]
mod time_02;
#[cfg(feature = "with-time-0_3")]
mod time_03;
#[cfg(feature = "with-uuid-0_8")]
mod uuid_08;
#[cfg(feature = "with-uuid-1")]
mod uuid_1;
#[cfg(feature = "with-time-0_2")]
extern crate time_02 as time;
mod pg_lsn;
#[doc(hidden)]
pub mod private;
mod special;
mod type_gen;
#[derive(PartialEq, Eq, Clone, Hash)]
pub struct Type(Inner);
impl fmt::Debug for Type {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.0, fmt)
}
}
impl fmt::Display for Type {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.schema() {
"public" | "pg_catalog" => {}
schema => write!(fmt, "{}.", schema)?,
}
fmt.write_str(self.name())
}
}
impl Type {
pub fn new(name: String, oid: Oid, kind: Kind, schema: String) -> Type {
Type(Inner::Other(Arc::new(Other {
name,
oid,
kind,
schema,
})))
}
pub fn from_oid(oid: Oid) -> Option<Type> {
Inner::from_oid(oid).map(Type)
}
pub fn oid(&self) -> Oid {
self.0.oid()
}
pub fn kind(&self) -> &Kind {
self.0.kind()
}
pub fn schema(&self) -> &str {
match self.0 {
Inner::Other(ref u) => &u.schema,
_ => "pg_catalog",
}
}
pub fn name(&self) -> &str {
self.0.name()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Kind {
Simple,
Enum(Vec<String>),
Pseudo,
Array(Type),
Range(Type),
Multirange(Type),
Domain(Type),
Composite(Vec<Field>),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Field {
name: String,
type_: Type,
}
impl Field {
pub fn new(name: String, type_: Type) -> Field {
Field { name, type_ }
}
pub fn name(&self) -> &str {
&self.name
}
pub fn type_(&self) -> &Type {
&self.type_
}
}
#[derive(Debug, Clone, Copy)]
pub struct WasNull;
impl fmt::Display for WasNull {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.write_str("a Postgres value was `NULL`")
}
}
impl Error for WasNull {}
#[derive(Debug)]
pub struct WrongType {
postgres: Type,
rust: &'static str,
}
impl fmt::Display for WrongType {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
fmt,
"cannot convert between the Rust type `{}` and the Postgres type `{}`",
self.rust, self.postgres,
)
}
}
impl Error for WrongType {}
impl WrongType {
pub fn new<T>(ty: Type) -> WrongType {
WrongType {
postgres: ty,
rust: type_name::<T>(),
}
}
}
pub trait FromSql<'a>: Sized {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>>;
#[allow(unused_variables)]
fn from_sql_null(ty: &Type) -> Result<Self, Box<dyn Error + Sync + Send>> {
Err(Box::new(WasNull))
}
fn from_sql_nullable(
ty: &Type,
raw: Option<&'a [u8]>,
) -> Result<Self, Box<dyn Error + Sync + Send>> {
match raw {
Some(raw) => Self::from_sql(ty, raw),
None => Self::from_sql_null(ty),
}
}
fn accepts(ty: &Type) -> bool;
}
pub trait FromSqlOwned: for<'a> FromSql<'a> {}
impl<T> FromSqlOwned for T where T: for<'a> FromSql<'a> {}
impl<'a, T: FromSql<'a>> FromSql<'a> for Option<T> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
<T as FromSql>::from_sql(ty, raw).map(Some)
}
fn from_sql_null(_: &Type) -> Result<Option<T>, Box<dyn Error + Sync + Send>> {
Ok(None)
}
fn accepts(ty: &Type) -> bool {
<T as FromSql>::accepts(ty)
}
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Vec<T>, Box<dyn Error + Sync + Send>> {
let member_type = match *ty.kind() {
Kind::Array(ref member) => member,
_ => panic!("expected array type"),
};
let array = types::array_from_sql(raw)?;
if array.dimensions().count()? > 1 {
return Err("array contains too many dimensions".into());
}
array
.values()
.map(|v| T::from_sql_nullable(member_type, v))
.collect()
}
fn accepts(ty: &Type) -> bool {
match *ty.kind() {
Kind::Array(ref inner) => T::accepts(inner),
_ => false,
}
}
}
#[cfg(feature = "array-impls")]
impl<'a, T: FromSql<'a>, const N: usize> FromSql<'a> for [T; N] {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
let member_type = match *ty.kind() {
Kind::Array(ref member) => member,
_ => panic!("expected array type"),
};
let array = types::array_from_sql(raw)?;
if array.dimensions().count()? > 1 {
return Err("array contains too many dimensions".into());
}
let mut values = array.values();
let out = array_init::try_array_init(|i| {
let v = values
.next()?
.ok_or_else(|| -> Box<dyn Error + Sync + Send> {
format!("too few elements in array (expected {}, got {})", N, i).into()
})?;
T::from_sql_nullable(member_type, v)
})?;
if values.next()?.is_some() {
return Err(format!(
"excess elements in array (expected {}, got more than that)",
N,
)
.into());
}
Ok(out)
}
fn accepts(ty: &Type) -> bool {
match *ty.kind() {
Kind::Array(ref inner) => T::accepts(inner),
_ => false,
}
}
}
impl<'a, T: FromSql<'a>> FromSql<'a> for Box<[T]> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
Vec::<T>::from_sql(ty, raw).map(Vec::into_boxed_slice)
}
fn accepts(ty: &Type) -> bool {
Vec::<T>::accepts(ty)
}
}
impl<'a> FromSql<'a> for Vec<u8> {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<Vec<u8>, Box<dyn Error + Sync + Send>> {
Ok(types::bytea_from_sql(raw).to_owned())
}
accepts!(BYTEA);
}
impl<'a> FromSql<'a> for &'a [u8] {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<&'a [u8], Box<dyn Error + Sync + Send>> {
Ok(types::bytea_from_sql(raw))
}
fn accepts(_: &Type) -> bool {
true
}
}
impl<'a> FromSql<'a> for String {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<String, Box<dyn Error + Sync + Send>> {
<&str as FromSql>::from_sql(ty, raw).map(ToString::to_string)
}
fn accepts(ty: &Type) -> bool {
<&str as FromSql>::accepts(ty)
}
}
impl<'a> FromSql<'a> for Box<str> {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<Box<str>, Box<dyn Error + Sync + Send>> {
<&str as FromSql>::from_sql(ty, raw)
.map(ToString::to_string)
.map(String::into_boxed_str)
}
fn accepts(ty: &Type) -> bool {
<&str as FromSql>::accepts(ty)
}
}
impl<'a> FromSql<'a> for &'a str {
fn from_sql(ty: &Type, raw: &'a [u8]) -> Result<&'a str, Box<dyn Error + Sync + Send>> {
match *ty {
ref ty if ty.name() == "ltree" => types::ltree_from_sql(raw),
ref ty if ty.name() == "lquery" => types::lquery_from_sql(raw),
ref ty if ty.name() == "ltxtquery" => types::ltxtquery_from_sql(raw),
_ => types::text_from_sql(raw),
}
}
fn accepts(ty: &Type) -> bool {
match *ty {
Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN => true,
ref ty
if (ty.name() == "citext"
|| ty.name() == "ltree"
|| ty.name() == "lquery"
|| ty.name() == "ltxtquery") =>
{
true
}
_ => false,
}
}
}
macro_rules! simple_from {
($t:ty, $f:ident,$oid:ident $(,$expected:ident)*) => {
impl<'a> FromSql<'a> for $t {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$t, Box<dyn Error + Sync + Send>> {
types::$f(raw)
}
fn accepts(ty: &Type) -> bool {
if matches!(*ty, $crate::Type::$oid) {
return true;
}
[
$(stringify!($expected)),*
].contains(&ty.name())
}
}
};
}
simple_from!(bool, bool_from_sql, BOOL);
simple_from!(i8, char_from_sql, CHAR, i8);
simple_from!(i16, int2_from_sql, INT2, i16);
simple_from!(i32, int4_from_sql, INT4, i32);
simple_from!(u32, oid_from_sql, OID, u32);
simple_from!(i64, int8_from_sql, INT8, i64);
simple_from!(f32, float4_from_sql, FLOAT4);
simple_from!(f64, float8_from_sql, FLOAT8);
macro_rules! int {
($ty:ident) => {
impl<'a> FromSql<'a> for $ty {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<$ty, Box<dyn Error + Sync + Send>> {
Ok($ty::from_be_bytes(raw.try_into()?))
}
fn accepts(ty: &Type) -> bool {
ty.name() == stringify!($ty)
}
}
};
($($ty:ident),+) => {
$(int!($ty);)+
};
}
int!(u64, u16);
impl<'a, S> FromSql<'a> for HashMap<String, Option<String>, S>
where
S: Default + BuildHasher,
{
fn from_sql(
_: &Type,
raw: &'a [u8],
) -> Result<HashMap<String, Option<String>, S>, Box<dyn Error + Sync + Send>> {
types::hstore_from_sql(raw)?
.map(|(k, v)| Ok((k.to_owned(), v.map(str::to_owned))))
.collect()
}
fn accepts(ty: &Type) -> bool {
ty.name() == "hstore"
}
}
impl<'a> FromSql<'a> for SystemTime {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<SystemTime, Box<dyn Error + Sync + Send>> {
let time = types::timestamp_from_sql(raw)?;
let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
let negative = time < 0;
let time = time.unsigned_abs();
let secs = time / USEC_PER_SEC;
let nsec = (time % USEC_PER_SEC) * NSEC_PER_USEC;
let offset = Duration::new(secs, nsec as u32);
let time = if negative {
epoch - offset
} else {
epoch + offset
};
Ok(time)
}
accepts!(TIMESTAMP, TIMESTAMPTZ);
}
impl<'a> FromSql<'a> for IpAddr {
fn from_sql(_: &Type, raw: &'a [u8]) -> Result<IpAddr, Box<dyn Error + Sync + Send>> {
let inet = types::inet_from_sql(raw)?;
Ok(inet.addr())
}
accepts!(INET);
}
pub enum IsNull {
Yes,
No,
}
pub trait ToSql: fmt::Debug {
fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>>
where
Self: Sized;
fn accepts(ty: &Type) -> bool
where
Self: Sized;
fn to_sql_checked(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>>;
fn encode_format(&self, _ty: &Type) -> Format {
Format::Binary
}
}
#[derive(Clone, Copy, Debug)]
pub enum Format {
Text,
Binary,
}
impl<'a, T> ToSql for &'a T
where
T: ToSql,
{
fn to_sql(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
(*self).to_sql(ty, out)
}
fn accepts(ty: &Type) -> bool {
T::accepts(ty)
}
fn encode_format(&self, ty: &Type) -> Format {
(*self).encode_format(ty)
}
to_sql_checked!();
}
impl<T: ToSql> ToSql for Option<T> {
fn to_sql(
&self,
ty: &Type,
out: &mut BytesMut,
) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
match *self {
Some(ref val) => val.to_sql(ty, out),
None => Ok(IsNull::Yes),
}
}
fn accepts(ty: &Type) -> bool {
<T as ToSql>::accepts(ty)
}
fn encode_format(&self, ty: &Type) -> Format {
match self {
Some(ref val) => val.encode_format(ty),
None => Format::Binary,
}
}
to_sql_checked!();
}
impl<'a, T: ToSql> ToSql for &'a [T] {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
let member_type = match *ty.kind() {
Kind::Array(ref member) => member,
_ => panic!("expected array type"),
};
let lower_bound = match *ty {
Type::OID_VECTOR | Type::INT2_VECTOR => 0,
_ => 1,
};
let dimension = ArrayDimension {
len: downcast(self.len())?,
lower_bound,
};
types::array_to_sql(
Some(dimension),
member_type.oid(),
self.iter(),
|e, w| match e.to_sql(member_type, w)? {
IsNull::No => Ok(postgres_protocol::IsNull::No),
IsNull::Yes => Ok(postgres_protocol::IsNull::Yes),
},
w,
)?;
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
match *ty.kind() {
Kind::Array(ref member) => T::accepts(member),
_ => false,
}
}
to_sql_checked!();
}
impl<'a> ToSql for &'a [u8] {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::bytea_to_sql(self, w);
Ok(IsNull::No)
}
accepts!(BYTEA);
to_sql_checked!();
}
#[cfg(feature = "array-impls")]
impl<const N: usize> ToSql for [u8; N] {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::bytea_to_sql(&self[..], w);
Ok(IsNull::No)
}
accepts!(BYTEA);
to_sql_checked!();
}
#[cfg(feature = "array-impls")]
impl<T: ToSql, const N: usize> ToSql for [T; N] {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&[T] as ToSql>::to_sql(&&self[..], ty, w)
}
fn accepts(ty: &Type) -> bool {
<&[T] as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl<T: ToSql> ToSql for Vec<T> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&[T] as ToSql>::to_sql(&&**self, ty, w)
}
fn accepts(ty: &Type) -> bool {
<&[T] as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl<T: ToSql> ToSql for Box<[T]> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&[T] as ToSql>::to_sql(&&**self, ty, w)
}
fn accepts(ty: &Type) -> bool {
<&[T] as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl<'a> ToSql for Cow<'a, [u8]> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&[u8] as ToSql>::to_sql(&self.as_ref(), ty, w)
}
fn accepts(ty: &Type) -> bool {
<&[u8] as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl ToSql for Vec<u8> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&[u8] as ToSql>::to_sql(&&**self, ty, w)
}
fn accepts(ty: &Type) -> bool {
<&[u8] as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl<'a> ToSql for &'a str {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
match ty.name() {
"ltree" => types::ltree_to_sql(self, w),
"lquery" => types::lquery_to_sql(self, w),
"ltxtquery" => types::ltxtquery_to_sql(self, w),
_ => types::text_to_sql(self, w),
}
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
matches!(
*ty,
Type::VARCHAR | Type::TEXT | Type::BPCHAR | Type::NAME | Type::UNKNOWN
) || matches!(ty.name(), "citext" | "ltree" | "lquery" | "ltxtquery")
}
to_sql_checked!();
}
impl<'a> ToSql for Cow<'a, str> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&str as ToSql>::to_sql(&self.as_ref(), ty, w)
}
fn accepts(ty: &Type) -> bool {
<&str as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl ToSql for String {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&str as ToSql>::to_sql(&&**self, ty, w)
}
fn accepts(ty: &Type) -> bool {
<&str as ToSql>::accepts(ty)
}
to_sql_checked!();
}
impl ToSql for Box<str> {
fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
<&str as ToSql>::to_sql(&&**self, ty, w)
}
fn accepts(ty: &Type) -> bool {
<&str as ToSql>::accepts(ty)
}
to_sql_checked!();
}
macro_rules! simple_to {
($t:ty, $f:ident,$oid:ident $(,$expected:ident)*) => {
impl ToSql for $t {
fn to_sql(&self,
_: &Type,
w: &mut BytesMut)
-> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::$f(*self, w);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
if matches!(*ty, $crate::Type::$oid) {
return true;
}
[
$(stringify!($expected)),*
].contains(&ty.name())
}
to_sql_checked!();
}
}
}
simple_to!(bool, bool_to_sql, BOOL);
simple_to!(i8, char_to_sql, CHAR, i8);
simple_to!(i16, int2_to_sql, INT2, i16);
simple_to!(i32, int4_to_sql, INT4, i32);
simple_to!(u32, oid_to_sql, OID, u32);
simple_to!(i64, int8_to_sql, INT8, i64);
simple_to!(f32, float4_to_sql, FLOAT4);
simple_to!(f64, float8_to_sql, FLOAT8);
impl ToSql for u16 {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
w.put_u16(*self);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
ty.name() == "u16"
}
to_sql_checked!();
}
impl ToSql for u64 {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
w.put_u64(*self);
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
ty.name() == "u64"
}
to_sql_checked!();
}
impl<H> ToSql for HashMap<String, Option<String>, H>
where
H: BuildHasher,
{
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
types::hstore_to_sql(
self.iter().map(|(k, v)| (&**k, v.as_ref().map(|v| &**v))),
w,
)?;
Ok(IsNull::No)
}
fn accepts(ty: &Type) -> bool {
ty.name() == "hstore"
}
to_sql_checked!();
}
impl ToSql for SystemTime {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
let epoch = UNIX_EPOCH + Duration::from_secs(TIME_SEC_CONVERSION);
let to_usec =
|d: Duration| d.as_secs() * USEC_PER_SEC + u64::from(d.subsec_nanos()) / NSEC_PER_USEC;
let time = match self.duration_since(epoch) {
Ok(duration) => to_usec(duration) as i64,
Err(e) => -(to_usec(e.duration()) as i64),
};
types::timestamp_to_sql(time, w);
Ok(IsNull::No)
}
accepts!(TIMESTAMP, TIMESTAMPTZ);
to_sql_checked!();
}
impl ToSql for IpAddr {
fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
let netmask = match self {
IpAddr::V4(_) => 32,
IpAddr::V6(_) => 128,
};
types::inet_to_sql(*self, netmask, w);
Ok(IsNull::No)
}
accepts!(INET);
to_sql_checked!();
}
fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
if len > i32::max_value() as usize {
Err("value too large to transmit".into())
} else {
Ok(len as i32)
}
}
mod sealed {
pub trait Sealed {}
}
pub trait BorrowToSql: sealed::Sealed {
fn borrow_to_sql(&self) -> &dyn ToSql;
}
impl sealed::Sealed for &dyn ToSql {}
impl BorrowToSql for &dyn ToSql {
#[inline]
fn borrow_to_sql(&self) -> &dyn ToSql {
*self
}
}
impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + 'a> {}
impl<'a> BorrowToSql for Box<dyn ToSql + Sync + 'a> {
#[inline]
fn borrow_to_sql(&self) -> &dyn ToSql {
self.as_ref()
}
}
impl<'a> sealed::Sealed for Box<dyn ToSql + Sync + Send + 'a> {}
impl<'a> BorrowToSql for Box<dyn ToSql + Sync + Send + 'a> {
#[inline]
fn borrow_to_sql(&self) -> &dyn ToSql {
self.as_ref()
}
}
impl sealed::Sealed for &(dyn ToSql + Sync) {}
impl BorrowToSql for &(dyn ToSql + Sync) {
#[inline]
fn borrow_to_sql(&self) -> &dyn ToSql {
*self
}
}
impl<T> sealed::Sealed for T where T: ToSql {}
impl<T> BorrowToSql for T
where
T: ToSql,
{
#[inline]
fn borrow_to_sql(&self) -> &dyn ToSql {
self
}
}