mod bytes;
mod numeric_util;
mod primitives;
pub mod ref_row;
mod row;
mod string;
pub use numeric_util::numeric_to_string;
#[cfg(feature = "with-chrono")]
mod chrono;
#[cfg(feature = "with-rust-decimal")]
mod decimal;
#[cfg(feature = "with-time")]
mod time;
#[cfg(feature = "with-uuid")]
mod uuid;
use crate::error::{Error, Result};
use crate::protocol::types::Oid;
pub use row::FromRow;
pub const PG_EPOCH_JULIAN_DAY: i32 = 2_451_545;
pub trait FromWireValue<'a>: Sized {
fn from_null() -> Result<Self> {
Err(Error::Decode("unexpected NULL value".into()))
}
fn from_text(oid: Oid, bytes: &'a [u8]) -> Result<Self>;
fn from_binary(oid: Oid, bytes: &'a [u8]) -> Result<Self>;
}
pub trait ToWireValue {
fn natural_oid(&self) -> Oid;
fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()>;
}
pub trait ToParams {
fn param_count(&self) -> usize;
fn natural_oids(&self) -> Vec<Oid>;
fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()>;
}
impl<'a, T: FromWireValue<'a>> FromWireValue<'a> for Option<T> {
fn from_null() -> Result<Self> {
Ok(None)
}
fn from_text(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
T::from_text(oid, bytes).map(Some)
}
fn from_binary(oid: Oid, bytes: &'a [u8]) -> Result<Self> {
T::from_binary(oid, bytes).map(Some)
}
}
impl<T: ToWireValue> ToWireValue for Option<T> {
fn natural_oid(&self) -> Oid {
match self {
Some(v) => v.natural_oid(),
None => 0, }
}
fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
match self {
Some(v) => v.encode(target_oid, buf),
None => {
buf.extend_from_slice(&(-1_i32).to_be_bytes());
Ok(())
}
}
}
}
impl<T: ToWireValue + ?Sized> ToWireValue for &T {
fn natural_oid(&self) -> Oid {
(*self).natural_oid()
}
fn encode(&self, target_oid: Oid, buf: &mut Vec<u8>) -> Result<()> {
(*self).encode(target_oid, buf)
}
}
impl ToParams for () {
fn param_count(&self) -> usize {
0
}
fn natural_oids(&self) -> Vec<Oid> {
vec![]
}
fn encode(&self, _target_oids: &[Oid], _buf: &mut Vec<u8>) -> Result<()> {
Ok(())
}
}
impl<T: ToParams + ?Sized> ToParams for &T {
fn param_count(&self) -> usize {
(*self).param_count()
}
fn natural_oids(&self) -> Vec<Oid> {
(*self).natural_oids()
}
fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
(*self).encode(target_oids, buf)
}
}
impl<T: ToWireValue> ToParams for [T] {
fn param_count(&self) -> usize {
self.len()
}
fn natural_oids(&self) -> Vec<Oid> {
self.iter().map(|v| v.natural_oid()).collect()
}
fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
for (v, &oid) in self.iter().zip(target_oids) {
v.encode(oid, buf)?;
}
Ok(())
}
}
impl<T: ToWireValue> ToParams for Vec<T> {
fn param_count(&self) -> usize {
self.as_slice().param_count()
}
fn natural_oids(&self) -> Vec<Oid> {
self.as_slice().natural_oids()
}
fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
self.as_slice().encode(target_oids, buf)
}
}
macro_rules! impl_to_params {
($count:expr, $($idx:tt: $T:ident),+) => {
impl<$($T: ToWireValue),+> ToParams for ($($T,)+) {
fn param_count(&self) -> usize {
$count
}
fn natural_oids(&self) -> Vec<Oid> {
vec![$(self.$idx.natural_oid()),+]
}
fn encode(&self, target_oids: &[Oid], buf: &mut Vec<u8>) -> Result<()> {
let mut _idx = 0;
$(
self.$idx.encode(target_oids[_idx], buf)?;
_idx += 1;
)+
Ok(())
}
}
};
}
impl_to_params!(1, 0: T0);
impl_to_params!(2, 0: T0, 1: T1);
impl_to_params!(3, 0: T0, 1: T1, 2: T2);
impl_to_params!(4, 0: T0, 1: T1, 2: T2, 3: T3);
impl_to_params!(5, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
impl_to_params!(6, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
impl_to_params!(7, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
impl_to_params!(8, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);
impl_to_params!(9, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8);
impl_to_params!(10, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9);
impl_to_params!(11, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10);
impl_to_params!(12, 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7, 8: T8, 9: T9, 10: T10, 11: T11);
#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::types::oid;
#[test]
fn option_null() {
assert_eq!(Option::<i32>::from_null().unwrap(), None);
}
#[test]
fn slice_to_params() {
let params: &[i32] = &[1, 2, 3];
assert_eq!(params.param_count(), 3);
assert_eq!(params.natural_oids(), vec![oid::INT4, oid::INT4, oid::INT4]);
let mut buf = Vec::new();
params
.encode(&[oid::INT4, oid::INT4, oid::INT4], &mut buf)
.unwrap();
assert_eq!(buf.len(), 3 * 8);
}
#[test]
fn vec_to_params() {
let params: Vec<i64> = vec![10, 20];
assert_eq!(params.param_count(), 2);
assert_eq!(params.natural_oids(), vec![oid::INT8, oid::INT8]);
let mut buf = Vec::new();
params.encode(&[oid::INT8, oid::INT8], &mut buf).unwrap();
assert_eq!(buf.len(), 2 * 12);
}
#[test]
fn empty_slice_to_params() {
let params: &[i32] = &[];
assert_eq!(params.param_count(), 0);
assert_eq!(params.natural_oids(), vec![]);
let mut buf = Vec::new();
params.encode(&[], &mut buf).unwrap();
assert!(buf.is_empty());
}
}