use alloc::string::ToString;
use alloc::vec::Vec;
use super::decoder::{
BoolDecoder, DateVerbatimDecoder, DecimalTextDecoder, Decoder, IntDecoder,
IntervalVerbatimDecoder, JsonVerbatimDecoder, NullDecoder, PgByteaBinaryDecoder, RealDecoder,
TextDecoder, TimeVerbatimDecoder, TimestampTzVerbatimDecoder, TimestampVerbatimDecoder,
UuidBlob16Decoder,
};
use super::error::DecodeError;
use super::scalar_helpers::{decode_pg_bool_binary, decode_pg_int_binary, decode_pg_real_binary};
use super::source::{PgBinary, PgBinaryColumn};
use super::type_map::{TypeMap, TypeMapDefaults};
use super::wire_type::WireType;
use crate::encoding::Value;
impl<S, B> Decoder<PgBinary, S, B> for NullDecoder {
fn decode(&self, _payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
Ok(Value::Null)
}
}
impl<S, B> Decoder<PgBinary, S, B> for BoolDecoder {
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
match payload.raw {
None => Ok(Value::Null),
Some(bytes) => decode_pg_bool_binary(payload.column_name, bytes),
}
}
}
impl<S, B> Decoder<PgBinary, S, B> for IntDecoder {
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
match payload.raw {
None => Ok(Value::Null),
Some(bytes) => decode_pg_int_binary(payload.column_name, bytes),
}
}
}
impl<S, B> Decoder<PgBinary, S, B> for RealDecoder {
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
match payload.raw {
None => Ok(Value::Null),
Some(bytes) => decode_pg_real_binary(payload.column_name, bytes),
}
}
}
impl<S, B> Decoder<PgBinary, S, B> for TextDecoder
where
S: From<alloc::string::String>,
{
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
let Some(bytes) = payload.raw else {
return Ok(Value::Null);
};
match core::str::from_utf8(bytes) {
Ok(s) => Ok(Value::Text(S::from(s.to_string()))),
Err(_) => Err(DecodeError::InvalidUtf8 {
column: payload.column_name.to_string(),
}),
}
}
}
impl<S, B> Decoder<PgBinary, S, B> for PgByteaBinaryDecoder
where
B: From<Vec<u8>>,
{
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
let Some(bytes) = payload.raw else {
return Ok(Value::Null);
};
Ok(Value::Blob(B::from(bytes.to_vec())))
}
}
impl<S, B> Decoder<PgBinary, S, B> for UuidBlob16Decoder
where
B: From<Vec<u8>>,
{
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
let Some(bytes) = payload.raw else {
return Ok(Value::Null);
};
if bytes.len() == 16 {
Ok(Value::Blob(B::from(bytes.to_vec())))
} else {
Err(DecodeError::InvalidUuid {
column: payload.column_name.to_string(),
source_len: bytes.len(),
})
}
}
}
macro_rules! not_yet_impl {
($decoder:ty) => {
impl<S, B> Decoder<PgBinary, S, B> for $decoder {
fn decode(&self, payload: PgBinaryColumn<'_>) -> Result<Value<S, B>, DecodeError> {
if payload.raw.is_none() {
return Ok(Value::Null);
}
Err(DecodeError::NotYetImplemented {
decoder: stringify!($decoder),
})
}
}
};
}
not_yet_impl!(DecimalTextDecoder);
not_yet_impl!(TimestampVerbatimDecoder);
not_yet_impl!(TimestampTzVerbatimDecoder);
not_yet_impl!(DateVerbatimDecoder);
not_yet_impl!(TimeVerbatimDecoder);
not_yet_impl!(IntervalVerbatimDecoder);
not_yet_impl!(JsonVerbatimDecoder);
impl<S, B> TypeMapDefaults<S, B> for PgBinary
where
S: From<alloc::string::String>,
B: From<Vec<u8>>,
{
fn defaults() -> TypeMap<Self, S, B> {
TypeMap::new()
.with(WireType::Bool, BoolDecoder)
.with(WireType::Int, IntDecoder)
.with(WireType::Real, RealDecoder)
.with(WireType::Text, TextDecoder)
.with(WireType::Bytes, PgByteaBinaryDecoder)
.with(WireType::Uuid, UuidBlob16Decoder)
.with(WireType::Decimal, DecimalTextDecoder)
.with(WireType::Timestamp, TimestampVerbatimDecoder)
.with(WireType::TimestampTz, TimestampTzVerbatimDecoder)
.with(WireType::Date, DateVerbatimDecoder)
.with(WireType::Time, TimeVerbatimDecoder)
.with(WireType::Interval, IntervalVerbatimDecoder)
.with(WireType::Json, JsonVerbatimDecoder)
.with(WireType::Jsonb, JsonVerbatimDecoder)
}
}