zero_postgres/protocol/
codec.rs1use crate::error::{Error, Result};
6use zerocopy::FromBytes;
7
8use zerocopy::byteorder::big_endian::{I16 as I16BE, I32 as I32BE, U16 as U16BE, U32 as U32BE};
9
10#[inline]
12pub fn read_u8(data: &[u8]) -> Result<(u8, &[u8])> {
13 if data.is_empty() {
14 return Err(Error::Protocol("read_u8: empty buffer".into()));
15 }
16 Ok((data[0], &data[1..]))
17}
18
19#[inline]
21pub fn read_i16(data: &[u8]) -> Result<(i16, &[u8])> {
22 if data.len() < 2 {
23 return Err(Error::Protocol(format!(
24 "read_i16: buffer too short: {} < 2",
25 data.len()
26 )));
27 }
28 let value = I16BE::ref_from_bytes(&data[..2])
29 .map_err(|e| Error::Protocol(format!("read_i16: {e:?}")))?
30 .get();
31 Ok((value, &data[2..]))
32}
33
34#[inline]
36pub fn read_u16(data: &[u8]) -> Result<(u16, &[u8])> {
37 if data.len() < 2 {
38 return Err(Error::Protocol(format!(
39 "read_u16: buffer too short: {} < 2",
40 data.len()
41 )));
42 }
43 let value = U16BE::ref_from_bytes(&data[..2])
44 .map_err(|e| Error::Protocol(format!("read_u16: {e:?}")))?
45 .get();
46 Ok((value, &data[2..]))
47}
48
49#[inline]
51pub fn read_i32(data: &[u8]) -> Result<(i32, &[u8])> {
52 if data.len() < 4 {
53 return Err(Error::Protocol(format!(
54 "read_i32: buffer too short: {} < 4",
55 data.len()
56 )));
57 }
58 let value = I32BE::ref_from_bytes(&data[..4])
59 .map_err(|e| Error::Protocol(format!("read_i32: {e:?}")))?
60 .get();
61 Ok((value, &data[4..]))
62}
63
64#[inline]
66pub fn read_u32(data: &[u8]) -> Result<(u32, &[u8])> {
67 if data.len() < 4 {
68 return Err(Error::Protocol(format!(
69 "read_u32: buffer too short: {} < 4",
70 data.len()
71 )));
72 }
73 let value = U32BE::ref_from_bytes(&data[..4])
74 .map_err(|e| Error::Protocol(format!("read_u32: {e:?}")))?
75 .get();
76 Ok((value, &data[4..]))
77}
78
79#[inline]
81pub fn read_bytes(data: &[u8], len: usize) -> Result<(&[u8], &[u8])> {
82 if data.len() < len {
83 return Err(Error::Protocol(format!(
84 "read_bytes: buffer too short: {} < {}",
85 data.len(),
86 len
87 )));
88 }
89 Ok((&data[..len], &data[len..]))
90}
91
92#[inline]
95pub fn read_cstring(data: &[u8]) -> Result<(&[u8], &[u8])> {
96 match memchr::memchr(0, data) {
97 Some(pos) => Ok((&data[..pos], &data[pos + 1..])),
98 None => Err(Error::Protocol(
99 "read_cstring: no null terminator found".into(),
100 )),
101 }
102}
103
104#[inline]
106pub fn read_cstr(data: &[u8]) -> Result<(&str, &[u8])> {
107 let (bytes, rest) = read_cstring(data)?;
108 let s = simdutf8::compat::from_utf8(bytes)
109 .map_err(|e| Error::Protocol(format!("read_cstr: invalid UTF-8: {e}")))?;
110 Ok((s, rest))
111}
112
113#[inline]
115pub fn write_u8(out: &mut Vec<u8>, value: u8) {
116 out.push(value);
117}
118
119#[inline]
121pub fn write_i16(out: &mut Vec<u8>, value: i16) {
122 out.extend_from_slice(&value.to_be_bytes());
123}
124
125#[inline]
127pub fn write_u16(out: &mut Vec<u8>, value: u16) {
128 out.extend_from_slice(&value.to_be_bytes());
129}
130
131#[inline]
133pub fn write_i32(out: &mut Vec<u8>, value: i32) {
134 out.extend_from_slice(&value.to_be_bytes());
135}
136
137#[inline]
139pub fn write_u32(out: &mut Vec<u8>, value: u32) {
140 out.extend_from_slice(&value.to_be_bytes());
141}
142
143#[inline]
145pub fn write_bytes(out: &mut Vec<u8>, data: &[u8]) {
146 out.extend_from_slice(data);
147}
148
149#[inline]
151pub fn write_cstring(out: &mut Vec<u8>, s: &[u8]) {
152 out.extend_from_slice(s);
153 out.push(0);
154}
155
156#[inline]
158pub fn write_cstr(out: &mut Vec<u8>, s: &str) {
159 write_cstring(out, s.as_bytes());
160}
161
162pub struct MessageBuilder<'a> {
169 buf: &'a mut Vec<u8>,
170 start: usize,
171}
172
173impl<'a> MessageBuilder<'a> {
174 pub fn new(buf: &'a mut Vec<u8>, type_byte: u8) -> Self {
176 buf.push(type_byte);
177 let start = buf.len();
178 buf.extend_from_slice(&[0, 0, 0, 0]); Self { buf, start }
180 }
181
182 pub fn new_startup(buf: &'a mut Vec<u8>) -> Self {
184 let start = buf.len();
185 buf.extend_from_slice(&[0, 0, 0, 0]); Self { buf, start }
187 }
188
189 pub fn buf(&mut self) -> &mut Vec<u8> {
191 self.buf
192 }
193
194 pub fn write_u8(&mut self, value: u8) {
196 write_u8(self.buf, value);
197 }
198
199 pub fn write_i16(&mut self, value: i16) {
201 write_i16(self.buf, value);
202 }
203
204 pub fn write_u16(&mut self, value: u16) {
206 write_u16(self.buf, value);
207 }
208
209 pub fn write_i32(&mut self, value: i32) {
211 write_i32(self.buf, value);
212 }
213
214 pub fn write_u32(&mut self, value: u32) {
216 write_u32(self.buf, value);
217 }
218
219 pub fn write_bytes(&mut self, data: &[u8]) {
221 write_bytes(self.buf, data);
222 }
223
224 pub fn write_cstr(&mut self, s: &str) {
226 write_cstr(self.buf, s);
227 }
228
229 pub fn finish(self) {
231 let len = (self.buf.len() - self.start) as u32;
232 self.buf[self.start..self.start + 4].copy_from_slice(&len.to_be_bytes());
233 }
234}