sqlx_core/postgres/message/
data_row.rs1use std::ops::Range;
2
3use byteorder::{BigEndian, ByteOrder};
4use bytes::Bytes;
5
6use crate::error::Error;
7use crate::io::Decode;
8
9#[derive(Debug)]
11pub struct DataRow {
12 pub(crate) storage: Bytes,
13
14 pub(crate) values: Vec<Option<Range<u32>>>,
18}
19
20impl DataRow {
21 #[inline]
22 pub(crate) fn get(&self, index: usize) -> Option<&'_ [u8]> {
23 self.values[index]
24 .as_ref()
25 .map(|col| &self.storage[(col.start as usize)..(col.end as usize)])
26 }
27}
28
29impl Decode<'_> for DataRow {
30 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
31 let cnt = BigEndian::read_u16(&buf) as usize;
32
33 let mut values = Vec::with_capacity(cnt);
34 let mut offset = 2;
35
36 for _ in 0..cnt {
37 let length = BigEndian::read_i32(&buf[(offset as usize)..]);
41 offset += 4;
42
43 if length < 0 {
44 values.push(None);
45 } else {
46 values.push(Some(offset..(offset + length as u32)));
47 offset += length as u32;
48 }
49 }
50
51 Ok(Self {
52 storage: buf,
53 values,
54 })
55 }
56}
57
58#[test]
59fn test_decode_data_row() {
60 const DATA: &[u8] = b"\x00\x08\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\n\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00(\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00P";
61
62 let row = DataRow::decode(DATA.into()).unwrap();
63
64 assert_eq!(row.values.len(), 8);
65
66 assert!(row.get(0).is_none());
67 assert_eq!(row.get(1).unwrap(), &[0_u8, 0, 0, 10][..]);
68 assert!(row.get(2).is_none());
69 assert_eq!(row.get(3).unwrap(), &[0_u8, 0, 0, 20][..]);
70 assert!(row.get(4).is_none());
71 assert_eq!(row.get(5).unwrap(), &[0_u8, 0, 0, 40][..]);
72 assert!(row.get(6).is_none());
73 assert_eq!(row.get(7).unwrap(), &[0_u8, 0, 0, 80][..]);
74}
75
76#[cfg(all(test, not(debug_assertions)))]
77#[bench]
78fn bench_data_row_get(b: &mut test::Bencher) {
79 const DATA: &[u8] = b"\x00\x08\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\n\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00(\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00P";
80
81 let row = DataRow::decode(test::black_box(Bytes::from_static(DATA))).unwrap();
82
83 b.iter(|| {
84 let _value = test::black_box(&row).get(3);
85 });
86}
87
88#[cfg(all(test, not(debug_assertions)))]
89#[bench]
90fn bench_decode_data_row(b: &mut test::Bencher) {
91 const DATA: &[u8] = b"\x00\x08\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\n\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00\x14\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00(\xff\xff\xff\xff\x00\x00\x00\x04\x00\x00\x00P";
92
93 b.iter(|| {
94 let _ = DataRow::decode(test::black_box(Bytes::from_static(DATA)));
95 });
96}