postgres_types_extra/
pg_snapshot.rs1use byteorder::{NetworkEndian, ReadBytesExt};
2use bytes::BufMut;
3use postgres_types::{FromSql, IsNull, ToSql, Type, to_sql_checked};
4use std::error::Error;
5use std::fmt;
6use std::io::Cursor;
7
8#[derive(Debug, PartialEq)]
9pub struct PgSnapshot {
10 xmin: i64,
11 xmax: i64,
12 xip_list: Vec<i64>,
13}
14
15impl<'a> FromSql<'a> for PgSnapshot {
16 fn from_sql(_ty: &Type, raw: &'a [u8]) -> Result<Self, Box<dyn Error + Sync + Send>> {
17 let mut rdr = Cursor::new(raw);
18
19 let nxip = rdr.read_i32::<NetworkEndian>()?;
20 let xmin = rdr.read_i64::<NetworkEndian>()?;
21 let xmax = rdr.read_i64::<NetworkEndian>()?;
22
23 let mut xip_list = Vec::with_capacity(nxip as usize);
24 for _ in 0..nxip {
25 xip_list.push(rdr.read_i64::<NetworkEndian>()?);
26 }
27
28 Ok(PgSnapshot {
29 xmin,
30 xmax,
31 xip_list,
32 })
33 }
34
35 fn accepts(ty: &Type) -> bool {
36 ty.name() == "pg_snapshot"
37 }
38}
39
40impl ToSql for PgSnapshot {
41 fn to_sql(
42 &self,
43 _ty: &Type,
44 out: &mut bytes::BytesMut,
45 ) -> Result<IsNull, Box<dyn Error + Sync + Send>> {
46 out.put_i32(self.xip_list.len() as i32);
47 out.put_i64(self.xmin);
48 out.put_i64(self.xmax);
49
50 for &xip in &self.xip_list {
51 out.put_i64(xip);
52 }
53
54 Ok(IsNull::No)
55 }
56
57 fn accepts(ty: &Type) -> bool {
58 ty.name() == "pg_snapshot"
59 }
60
61 to_sql_checked!();
62}
63
64impl fmt::Display for PgSnapshot {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 write!(f, "{}:{}", self.xmin, self.xmax)?;
67 if !self.xip_list.is_empty() {
68 write!(f, ":")?;
69 for (i, xip) in self.xip_list.iter().enumerate() {
70 if i > 0 {
71 write!(f, ",")?;
72 }
73 write!(f, "{xip}")?;
74 }
75 } else {
76 write!(f, ":")?;
77 }
78 Ok(())
79 }
80}