sentinel_driver/types/
bit.rs1use bytes::{BufMut, BytesMut};
2
3use crate::error::{Error, Result};
4use crate::types::{FromSql, Oid, ToSql};
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
12pub struct PgBit {
13 pub data: Vec<u8>,
14 pub bit_length: i32,
15}
16
17impl PgBit {
18 pub fn from_bools(bits: &[bool]) -> Self {
20 let bit_length = bits.len() as i32;
21 let byte_count = bits.len().div_ceil(8);
22 let mut data = vec![0u8; byte_count];
23
24 for (i, &bit) in bits.iter().enumerate() {
25 if bit {
26 data[i / 8] |= 1 << (7 - (i % 8));
27 }
28 }
29
30 PgBit { data, bit_length }
31 }
32
33 pub fn get(&self, index: usize) -> Option<bool> {
35 if index >= self.bit_length as usize {
36 return None;
37 }
38 Some(self.data[index / 8] & (1 << (7 - (index % 8))) != 0)
39 }
40
41 pub fn len(&self) -> usize {
43 self.bit_length as usize
44 }
45
46 pub fn is_empty(&self) -> bool {
48 self.bit_length == 0
49 }
50}
51
52impl ToSql for PgBit {
53 fn oid(&self) -> Oid {
54 Oid::VARBIT
55 }
56
57 fn to_sql(&self, buf: &mut BytesMut) -> Result<()> {
58 buf.put_i32(self.bit_length);
59 buf.put_slice(&self.data);
60 Ok(())
61 }
62}
63
64impl FromSql for PgBit {
65 fn oid() -> Oid {
66 Oid::VARBIT
67 }
68
69 fn from_sql(buf: &[u8]) -> Result<Self> {
70 if buf.len() < 4 {
71 return Err(Error::Decode(format!(
72 "bit: expected at least 4 bytes, got {}",
73 buf.len()
74 )));
75 }
76
77 let bit_length = i32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
78
79 if bit_length < 0 {
80 return Err(Error::Decode(format!(
81 "bit: negative bit length {bit_length}"
82 )));
83 }
84
85 let byte_count = (bit_length as usize).div_ceil(8);
86
87 if buf.len() < 4 + byte_count {
88 return Err(Error::Decode(format!(
89 "bit: expected {} data bytes for {} bits, got {}",
90 byte_count,
91 bit_length,
92 buf.len() - 4
93 )));
94 }
95
96 let data = buf[4..4 + byte_count].to_vec();
97
98 Ok(PgBit { data, bit_length })
99 }
100}