use sqlx::{
Decode, Encode,
encode::IsNull,
error::BoxDynError,
postgres::{PgArgumentBuffer, PgTypeInfo, PgValueRef, Postgres},
};
use uuid::Uuid;
use crate::{HeerId, HeerIdDesc, RanjId, RanjIdDesc};
impl sqlx::Type<Postgres> for HeerId {
fn type_info() -> PgTypeInfo {
<i64 as sqlx::Type<Postgres>>::type_info()
}
fn compatible(ty: &PgTypeInfo) -> bool {
<i64 as sqlx::Type<Postgres>>::compatible(ty)
}
}
impl<'r> Decode<'r, Postgres> for HeerId {
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
let raw = <i64 as Decode<Postgres>>::decode(value)?;
HeerId::from_i64(raw).map_err(|e| Box::new(e) as BoxDynError)
}
}
impl Encode<'_, Postgres> for HeerId {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
<i64 as Encode<Postgres>>::encode_by_ref(&self.as_i64(), buf)
}
}
impl sqlx::Type<Postgres> for RanjId {
fn type_info() -> PgTypeInfo {
<Uuid as sqlx::Type<Postgres>>::type_info()
}
fn compatible(ty: &PgTypeInfo) -> bool {
<Uuid as sqlx::Type<Postgres>>::compatible(ty)
}
}
impl<'r> Decode<'r, Postgres> for RanjId {
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
let uuid = <Uuid as Decode<Postgres>>::decode(value)?;
RanjId::from_uuid(uuid).map_err(|e| Box::new(e) as BoxDynError)
}
}
impl Encode<'_, Postgres> for RanjId {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
<Uuid as Encode<Postgres>>::encode_by_ref(&self.as_uuid(), buf)
}
}
impl sqlx::Type<Postgres> for HeerIdDesc {
fn type_info() -> PgTypeInfo {
<i64 as sqlx::Type<Postgres>>::type_info()
}
fn compatible(ty: &PgTypeInfo) -> bool {
<i64 as sqlx::Type<Postgres>>::compatible(ty)
}
}
impl<'r> Decode<'r, Postgres> for HeerIdDesc {
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
let raw = <i64 as Decode<Postgres>>::decode(value)?;
HeerIdDesc::from_i64(raw).map_err(|e| Box::new(e) as BoxDynError)
}
}
impl Encode<'_, Postgres> for HeerIdDesc {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
<i64 as Encode<Postgres>>::encode_by_ref(&self.as_i64(), buf)
}
}
impl sqlx::Type<Postgres> for RanjIdDesc {
fn type_info() -> PgTypeInfo {
<Uuid as sqlx::Type<Postgres>>::type_info()
}
fn compatible(ty: &PgTypeInfo) -> bool {
<Uuid as sqlx::Type<Postgres>>::compatible(ty)
}
}
impl<'r> Decode<'r, Postgres> for RanjIdDesc {
fn decode(value: PgValueRef<'r>) -> Result<Self, BoxDynError> {
let u = <Uuid as Decode<Postgres>>::decode(value)?;
RanjIdDesc::from_uuid(u).map_err(|e| Box::new(e) as BoxDynError)
}
}
impl Encode<'_, Postgres> for RanjIdDesc {
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> Result<IsNull, BoxDynError> {
<Uuid as Encode<Postgres>>::encode_by_ref(&self.as_uuid(), buf)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::RanjPrecision;
use sqlx::Type;
#[test]
fn heerid_type_info_matches_bigint() {
assert_eq!(
<HeerId as Type<Postgres>>::type_info(),
<i64 as Type<Postgres>>::type_info(),
);
}
#[test]
fn ranjid_type_info_matches_uuid() {
assert_eq!(
<RanjId as Type<Postgres>>::type_info(),
<Uuid as Type<Postgres>>::type_info(),
);
}
#[test]
fn heerid_encode_matches_i64_wire_format() {
let id = HeerId::new(1_234_567_890, 42, 7).unwrap();
let raw: i64 = id.as_i64();
let mut our_buf = PgArgumentBuffer::default();
let _ = <HeerId as Encode<Postgres>>::encode_by_ref(&id, &mut our_buf).unwrap();
let mut ref_buf = PgArgumentBuffer::default();
let _ = <i64 as Encode<Postgres>>::encode_by_ref(&raw, &mut ref_buf).unwrap();
assert_eq!(&**our_buf, &**ref_buf);
}
#[test]
fn ranjid_encode_matches_uuid_wire_format() {
let id = RanjId::new(42, RanjPrecision::Microseconds, 7, 1).unwrap();
let raw: Uuid = id.as_uuid();
let mut our_buf = PgArgumentBuffer::default();
let _ = <RanjId as Encode<Postgres>>::encode_by_ref(&id, &mut our_buf).unwrap();
let mut ref_buf = PgArgumentBuffer::default();
let _ = <Uuid as Encode<Postgres>>::encode_by_ref(&raw, &mut ref_buf).unwrap();
assert_eq!(&**our_buf, &**ref_buf);
}
}