use alloc::string::ToString;
use super::error::DecodeError;
use crate::encoding::Value;
#[inline]
pub(crate) fn normalize_real<S, B>(f: f64) -> Value<S, B> {
if f.is_nan() {
Value::Null
} else if f == 0.0 {
Value::Real(0.0)
} else {
Value::Real(f)
}
}
pub(crate) fn decode_pg_int_binary<S, B>(
column_name: &str,
bytes: &[u8],
) -> Result<Value<S, B>, DecodeError> {
match bytes.len() {
2 => {
let arr: [u8; 2] = bytes.try_into().unwrap();
Ok(Value::Integer(i16::from_be_bytes(arr).into()))
}
4 => {
let arr: [u8; 4] = bytes.try_into().unwrap();
Ok(Value::Integer(i32::from_be_bytes(arr).into()))
}
8 => {
let arr: [u8; 8] = bytes.try_into().unwrap();
Ok(Value::Integer(i64::from_be_bytes(arr)))
}
_ => Err(DecodeError::WrongPayloadKind {
column: column_name.to_string(),
expected: "int2, int4, or int8 binary (2, 4, or 8 bytes)",
actual: "unexpected binary integer width",
}),
}
}
pub(crate) fn decode_pg_real_binary<S, B>(
column_name: &str,
bytes: &[u8],
) -> Result<Value<S, B>, DecodeError> {
match bytes.len() {
4 => {
let arr: [u8; 4] = bytes.try_into().unwrap();
Ok(normalize_real(f64::from(f32::from_be_bytes(arr))))
}
8 => {
let arr: [u8; 8] = bytes.try_into().unwrap();
Ok(normalize_real(f64::from_be_bytes(arr)))
}
_ => Err(DecodeError::WrongPayloadKind {
column: column_name.to_string(),
expected: "float4 or float8 binary (4 or 8 bytes)",
actual: "unexpected binary float width",
}),
}
}
pub(crate) fn decode_pg_bool_binary<S, B>(
column_name: &str,
bytes: &[u8],
) -> Result<Value<S, B>, DecodeError> {
match bytes {
[0x01] => Ok(Value::Integer(1)),
[0x00] => Ok(Value::Integer(0)),
_ => Err(DecodeError::WrongPayloadKind {
column: column_name.to_string(),
expected: "single byte 0x00 or 0x01",
actual: "other binary contents",
}),
}
}