rbdc_pg/message/
data_row.rs1use std::ops::Range;
2
3use byteorder::{BigEndian, ByteOrder};
4use bytes::Bytes;
5use rbdc::io::Decode;
6use rbdc::Error;
7
8#[derive(Debug)]
10pub struct DataRow {
11 pub storage: Vec<Option<Vec<u8>>>,
12 pub values: Vec<Option<Range<usize>>>,
16}
17
18impl DataRow {
19 #[inline]
20 pub(crate) fn get(&self, index: usize) -> Option<&'_ [u8]> {
21 let mut idx = 0;
22 for x in &self.values {
23 if index == idx {
24 match x {
25 None => return None,
26 Some(_) => match &self.storage[idx] {
27 None => {
28 return None;
29 }
30 Some(v) => {
31 return Some(v);
32 }
33 },
34 }
35 }
36 idx += 1;
37 }
38 None
39 }
40
41 #[inline]
42 pub(crate) fn take(&mut self, index: usize) -> Option<Vec<u8>> {
43 let mut idx = 0;
44 for x in &self.values {
45 if index == idx {
46 match x {
47 None => return None,
48 Some(_) => {
49 return match self.storage[idx].take() {
50 None => None,
51 Some(v) => Some(v),
52 }
53 }
54 }
55 }
56 idx += 1;
57 }
58 None
59 }
60}
61
62impl Decode<'_> for DataRow {
63 fn decode_with(buf: Bytes, _: ()) -> Result<Self, Error> {
64 let cnt = BigEndian::read_u16(&buf) as usize;
65
66 let mut values = Vec::with_capacity(cnt);
67 let mut offset = 2;
68
69 for _ in 0..cnt {
70 let length = BigEndian::read_i32(&buf[(offset as usize)..]);
74 offset += 4;
75
76 if length < 0 {
77 values.push(None);
78 } else {
79 values.push(Some(offset as usize..(offset + length as u32) as usize));
80 offset += length as u32;
81 }
82 }
83 let mut storage = Vec::with_capacity(values.len());
84 for x in &values {
85 match x {
86 None => {
87 storage.push(None);
88 }
89 Some(v) => storage.push(Some(buf[v.start..v.end].to_vec())),
90 }
91 }
92 Ok(Self {
93 storage: storage,
94 values: values,
95 })
96 }
97}
98
99#[test]
100fn test_decode_data_row() {
101 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";
102
103 let row = DataRow::decode(DATA.into()).unwrap();
104
105 assert_eq!(row.values.len(), 8);
106
107 assert!(row.get(0).is_none());
108 assert_eq!(row.get(1).unwrap(), &[0_u8, 0, 0, 10][..]);
109 assert!(row.get(2).is_none());
110 assert_eq!(row.get(3).unwrap(), &[0_u8, 0, 0, 20][..]);
111 assert!(row.get(4).is_none());
112 assert_eq!(row.get(5).unwrap(), &[0_u8, 0, 0, 40][..]);
113 assert!(row.get(6).is_none());
114 assert_eq!(row.get(7).unwrap(), &[0_u8, 0, 0, 80][..]);
115}
116
117#[cfg(all(test, not(debug_assertions)))]
118#[bench]
119fn bench_data_row_get(b: &mut test::Bencher) {
120 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";
121
122 let row = DataRow::decode(test::black_box(Bytes::from_static(DATA))).unwrap();
123
124 b.iter(|| {
125 let _value = test::black_box(&row).get(3);
126 });
127}
128
129#[cfg(all(test, not(debug_assertions)))]
130#[bench]
131fn bench_decode_data_row(b: &mut test::Bencher) {
132 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";
133
134 b.iter(|| {
135 let _ = DataRow::decode(test::black_box(Bytes::from_static(DATA)));
136 });
137}