firebird_wire/wire/
xdr.rs1#![allow(missing_docs)]
9
10use crate::error::{Error, Result};
11
12#[inline]
14pub const fn pad4(n: usize) -> usize {
15 (n + 3) & !3
16}
17
18#[derive(Debug, Default, Clone)]
20pub struct XdrWriter {
21 buf: Vec<u8>,
22}
23
24impl XdrWriter {
25 #[inline]
26 pub fn new() -> Self {
27 Self {
28 buf: Vec::with_capacity(64),
29 }
30 }
31
32 #[inline]
33 pub fn with_capacity(cap: usize) -> Self {
34 Self {
35 buf: Vec::with_capacity(cap),
36 }
37 }
38
39 #[inline]
40 pub fn len(&self) -> usize {
41 self.buf.len()
42 }
43
44 #[inline]
45 pub fn is_empty(&self) -> bool {
46 self.buf.is_empty()
47 }
48
49 #[inline]
50 pub fn as_slice(&self) -> &[u8] {
51 &self.buf
52 }
53
54 #[inline]
55 pub fn into_vec(self) -> Vec<u8> {
56 self.buf
57 }
58
59 #[inline]
61 pub fn put_i32(&mut self, v: i32) -> &mut Self {
62 self.buf.extend_from_slice(&v.to_be_bytes());
63 self
64 }
65
66 #[inline]
67 pub fn put_u32(&mut self, v: u32) -> &mut Self {
68 self.buf.extend_from_slice(&v.to_be_bytes());
69 self
70 }
71
72 #[inline]
74 pub fn put_i64(&mut self, v: i64) -> &mut Self {
75 self.buf.extend_from_slice(&v.to_be_bytes());
76 self
77 }
78
79 #[inline]
80 pub fn put_f64(&mut self, v: f64) -> &mut Self {
81 self.buf.extend_from_slice(&v.to_be_bytes());
82 self
83 }
84
85 #[inline]
87 pub fn put_raw(&mut self, bytes: &[u8]) -> &mut Self {
88 self.buf.extend_from_slice(bytes);
89 self
90 }
91
92 #[inline]
94 pub fn align(&mut self) -> &mut Self {
95 while !self.buf.len().is_multiple_of(4) {
96 self.buf.push(0);
97 }
98 self
99 }
100
101 pub fn put_bytes(&mut self, data: &[u8]) -> &mut Self {
105 self.put_i32(data.len() as i32);
106 self.buf.extend_from_slice(data);
107 self.align();
108 self
109 }
110
111 #[inline]
113 pub fn put_str(&mut self, s: &str) -> &mut Self {
114 self.put_bytes(s.as_bytes())
115 }
116}
117
118#[derive(Debug, Clone)]
120pub struct XdrReader<'a> {
121 buf: &'a [u8],
122 pos: usize,
123}
124
125impl<'a> XdrReader<'a> {
126 #[inline]
127 pub fn new(buf: &'a [u8]) -> Self {
128 Self { buf, pos: 0 }
129 }
130
131 #[inline]
132 pub fn position(&self) -> usize {
133 self.pos
134 }
135
136 #[inline]
137 pub fn remaining(&self) -> usize {
138 self.buf.len() - self.pos
139 }
140
141 #[inline]
142 pub fn is_empty(&self) -> bool {
143 self.remaining() == 0
144 }
145
146 fn need(&self, n: usize) -> Result<()> {
147 if self.remaining() < n {
148 return Err(Error::protocol(format!(
149 "short XDR read: need {n} bytes, have {}",
150 self.remaining()
151 )));
152 }
153 Ok(())
154 }
155
156 #[inline]
157 pub fn get_i32(&mut self) -> Result<i32> {
158 self.need(4)?;
159 let v = i32::from_be_bytes(self.buf[self.pos..self.pos + 4].try_into().unwrap());
160 self.pos += 4;
161 Ok(v)
162 }
163
164 #[inline]
165 pub fn get_u32(&mut self) -> Result<u32> {
166 Ok(self.get_i32()? as u32)
167 }
168
169 #[inline]
170 pub fn get_i64(&mut self) -> Result<i64> {
171 self.need(8)?;
172 let v = i64::from_be_bytes(self.buf[self.pos..self.pos + 8].try_into().unwrap());
173 self.pos += 8;
174 Ok(v)
175 }
176
177 #[inline]
178 pub fn get_f64(&mut self) -> Result<f64> {
179 Ok(f64::from_bits(self.get_i64()? as u64))
180 }
181
182 pub fn get_raw(&mut self, n: usize) -> Result<&'a [u8]> {
184 self.need(n)?;
185 let s = &self.buf[self.pos..self.pos + n];
186 self.pos += n;
187 Ok(s)
188 }
189
190 #[inline]
192 pub fn align(&mut self) -> Result<()> {
193 let pad = pad4(self.pos) - self.pos;
194 if pad > 0 {
195 self.need(pad)?;
196 self.pos += pad;
197 }
198 Ok(())
199 }
200
201 pub fn get_bytes(&mut self) -> Result<&'a [u8]> {
204 let len = self.get_i32()? as usize;
205 let data = self.get_raw(len)?;
206 self.align()?;
207 Ok(data)
208 }
209
210 pub fn get_bytes_owned(&mut self) -> Result<Vec<u8>> {
212 Ok(self.get_bytes()?.to_vec())
213 }
214}
215
216#[derive(Debug, Clone)]
226pub struct ParameterBuffer {
227 buf: Vec<u8>,
228}
229
230impl ParameterBuffer {
231 pub fn new(version: u8) -> Self {
233 Self { buf: vec![version] }
234 }
235
236 pub fn raw() -> Self {
238 Self { buf: Vec::new() }
239 }
240
241 #[inline]
242 pub fn is_empty(&self) -> bool {
243 self.buf.len() <= 1
245 }
246
247 pub fn tag(&mut self, tag: u8) -> &mut Self {
249 self.buf.push(tag);
250 self
251 }
252
253 pub fn bytes(&mut self, tag: u8, value: &[u8]) -> &mut Self {
255 debug_assert!(value.len() <= u8::MAX as usize, "clumplet value too long");
256 self.buf.push(tag);
257 self.buf.push(value.len() as u8);
258 self.buf.extend_from_slice(value);
259 self
260 }
261
262 #[inline]
263 pub fn string(&mut self, tag: u8, value: &str) -> &mut Self {
264 self.bytes(tag, value.as_bytes())
265 }
266
267 pub fn int(&mut self, tag: u8, value: i32) -> &mut Self {
271 let le = value.to_le_bytes();
272 let mut n = 4;
274 while n > 1 && le[n - 1] == 0 {
275 n -= 1;
276 }
277 self.bytes(tag, &le[..n])
278 }
279
280 pub fn int_u32(&mut self, tag: u8, value: u32) -> &mut Self {
282 self.bytes(tag, &value.to_le_bytes())
283 }
284
285 pub fn int_u64(&mut self, tag: u8, value: u64) -> &mut Self {
287 self.bytes(tag, &value.to_le_bytes())
288 }
289
290 pub fn bytes_be_len4(&mut self, tag: u8, value: &[u8]) -> &mut Self {
293 self.buf.push(tag);
294 self.buf
295 .extend_from_slice(&(value.len() as u32).to_le_bytes());
296 self.buf.extend_from_slice(value);
297 self
298 }
299
300 #[inline]
301 pub fn as_slice(&self) -> &[u8] {
302 &self.buf
303 }
304
305 #[inline]
306 pub fn into_vec(self) -> Vec<u8> {
307 self.buf
308 }
309}
310
311pub fn read_le_int(bytes: &[u8]) -> i64 {
314 let mut v: i64 = 0;
315 for (i, &b) in bytes.iter().enumerate().take(8) {
316 v |= (b as i64) << (8 * i);
317 }
318 v
319}
320
321pub fn read_le_int_signed(bytes: &[u8]) -> i64 {
324 let v = read_le_int(bytes);
325 let width = bytes.len().min(8);
326 if width == 0 || width == 8 {
327 return v;
328 }
329 let bits = width * 8;
330 let sign = 1i64 << (bits - 1);
331 if v & sign != 0 {
332 v | !((1i64 << bits) - 1) } else {
334 v
335 }
336}
337
338#[cfg(test)]
339mod tests {
340 use super::*;
341
342 #[test]
343 fn roundtrip_ints_and_bytes() {
344 let mut w = XdrWriter::new();
345 w.put_i32(-7)
346 .put_i64(1 << 40)
347 .put_bytes(b"hello")
348 .put_str("hi");
349 let bytes = w.into_vec();
350
351 let mut r = XdrReader::new(&bytes);
352 assert_eq!(r.get_i32().unwrap(), -7);
353 assert_eq!(r.get_i64().unwrap(), 1 << 40);
354 assert_eq!(r.get_bytes().unwrap(), b"hello");
355 assert_eq!(r.get_bytes().unwrap(), b"hi");
356 assert!(r.is_empty());
357 }
358
359 #[test]
360 fn put_bytes_is_padded() {
361 let mut w = XdrWriter::new();
362 w.put_bytes(b"abc"); assert_eq!(w.len(), 8);
364 assert_eq!(&w.as_slice()[4..7], b"abc");
365 assert_eq!(w.as_slice()[7], 0);
366 }
367
368 #[test]
369 fn clumplet_minimal_int_width() {
370 let mut pb = ParameterBuffer::new(crate::wire::consts::DPB_VERSION1);
371 pb.int(crate::wire::consts::dpb::SQL_DIALECT, 3);
372 assert_eq!(pb.as_slice(), &[1, 63, 1, 3]);
374 }
375
376 #[test]
377 fn le_int_decode() {
378 assert_eq!(read_le_int(&[0x10, 0x27]), 10000);
379 assert_eq!(read_le_int(&[0xff]), 255);
380 }
381}