refactor: add standalone PgOid type

This commit is contained in:
Jindřich Moravec 2024-02-01 22:27:58 +01:00
parent bdb6a955df
commit 6d1af26fa8
10 changed files with 136 additions and 66 deletions

View file

@ -1,6 +1,7 @@
use crate::message::errors::{ProtoDeserializeError, ProtoSerializeError};
use crate::message::primitive::data::MessageData;
use crate::message::primitive::pglist::PgList;
use crate::message::primitive::pgoid::PgOid;
use crate::message::primitive::pgstring::PgString;
use crate::message::proto_message::ProtoMessage;
use bincode::{Decode, Encode};
@ -186,9 +187,9 @@ impl From<RowDescriptionData> for BackendMessage {
#[derive(Debug, Clone, Encode, Decode)]
pub struct ColumnDescription {
pub name: PgString,
pub table_oid: i32,
pub table_oid: PgOid,
pub column_index: i16,
pub type_oid: i32,
pub type_oid: PgOid,
pub type_size: i16,
pub type_modifier: i32,
pub format_code: i16,
@ -330,9 +331,9 @@ mod tests {
let backend = BackendMessage::RowDescription(RowDescriptionData {
columns: PgList::from(vec![ColumnDescription {
name: PgString::from("Some name"),
table_oid: 123,
table_oid: PgOid::Simple(123),
column_index: 456,
type_oid: 789,
type_oid: PgOid::Simple(789),
type_size: 101,
type_modifier: 112,
format_code: 113,
@ -347,9 +348,9 @@ mod tests {
let columns: Vec<ColumnDescription> = columns.into();
let column = &columns[0];
column.name.as_str() == "Some name"
&& column.table_oid == 123
&& column.table_oid.as_simple() == 123
&& column.column_index == 456
&& column.type_oid == 789
&& column.type_oid.as_simple() == 789
&& column.type_size == 101
&& column.type_modifier == 112
&& column.format_code == 113

View file

@ -1,3 +1,4 @@
pub(crate) mod data;
pub mod pglist;
pub mod pgoid;
pub mod pgstring;

View file

@ -0,0 +1,79 @@
use bincode::de::Decoder;
use bincode::enc::Encoder;
use bincode::error::{DecodeError, EncodeError};
use bincode::{BorrowDecode, Decode, Encode};
use rand::Rng;
use rand_pcg::Pcg64;
use rand_seeder::Seeder;
use std::fmt::Display;
#[derive(Debug, Clone, Copy, BorrowDecode)]
pub enum PgOid {
Simple(i32),
Nested(u16, u16),
}
impl PgOid {
/// Generates a pseudo-random OID from a name.
pub fn from_unique_name(name: &str) -> PgOid {
let mut rng: Pcg64 = Seeder::from(name).make_rng();
let oid = rng.gen::<i32>();
PgOid::Simple(oid)
}
pub fn as_nested(&self) -> (u16, u16) {
match self {
PgOid::Nested(a, b) => (*a, *b),
PgOid::Simple(oid) => {
let type_part = (oid & 0x0000FFFF) as u16;
let nest_part = (((*oid as u32) & 0xFFFF0000) >> 16) as u16;
(type_part, nest_part)
}
}
}
pub fn as_simple(&self) -> i32 {
match self {
PgOid::Simple(oid) => *oid,
PgOid::Nested(type_part, nest_part) => {
let oid = (*type_part as u32) | ((*nest_part as u32) << 16);
oid as i32
}
}
}
}
impl Display for PgOid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let oid = self.as_simple();
write!(f, "{}", oid)
}
}
impl Encode for PgOid {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
let oid = self.as_simple();
oid.encode(encoder)
}
}
impl Decode for PgOid {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let oid = i32::decode(decoder)?;
Ok(PgOid::Simple(oid))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pgoid() {
let oid = PgOid::Simple(0x12345678);
let (type_part, nest_part) = oid.as_nested();
assert_eq!(type_part, 0x5678);
assert_eq!(nest_part, 0x1234);
assert_eq!(oid.as_simple(), 0x12345678);
}
}