1use spvirit_codec::spvd_decode::{DecodedValue, PvdDecoder, StructureDesc};
8use spvirit_codec::spvd_encode::encode_size_pvd;
9
10pub fn decode_put_body(body: &[u8], desc: &StructureDesc, is_be: bool) -> Option<DecodedValue> {
16 let decoder = PvdDecoder::new(is_be);
17 if let Some((value, _)) = decoder.decode_structure_with_bitset(body, desc) {
18 if !decoded_is_empty(&value) {
19 return Some(value);
20 }
21 }
22 if !body.is_empty() && body[0] == 0xFF {
23 if let Some((value, _)) = decoder.decode_structure_with_bitset(&body[1..], desc) {
24 if !decoded_is_empty(&value) {
25 return Some(value);
26 }
27 }
28 }
29 if let Some(value) = decode_put_body_shifted_bitset(body, desc, is_be) {
30 return Some(value);
31 }
32 if let Some(value) = decode_put_body_value_only(body, desc, is_be) {
33 return Some(value);
34 }
35 None
36}
37
38fn decoded_is_empty(value: &DecodedValue) -> bool {
39 matches!(value, DecodedValue::Structure(fields) if fields.is_empty())
40}
41
42fn decode_put_body_shifted_bitset(
43 body: &[u8],
44 desc: &StructureDesc,
45 is_be: bool,
46) -> Option<DecodedValue> {
47 let decoder = PvdDecoder::new(is_be);
48 let (size, consumed) = decoder.decode_size(body)?;
49 if size == 0 || body.len() < consumed + size {
50 return None;
51 }
52 let bitset = &body[consumed..consumed + size];
53 let data = &body[consumed + size..];
54 let shifted = shift_bitset_left(bitset, 1);
55 let mut shifted_body = Vec::new();
56 shifted_body.extend_from_slice(&encode_size_pvd(shifted.len(), is_be));
57 shifted_body.extend_from_slice(&shifted);
58 shifted_body.extend_from_slice(data);
59 decoder
60 .decode_structure_with_bitset(&shifted_body, desc)
61 .map(|(value, _)| value)
62 .filter(|value| !decoded_is_empty(value))
63}
64
65fn decode_put_body_value_only(
66 body: &[u8],
67 desc: &StructureDesc,
68 is_be: bool,
69) -> Option<DecodedValue> {
70 let decoder = PvdDecoder::new(is_be);
71 if let Some((size, consumed)) = decoder.decode_size(body) {
72 if consumed + size <= body.len() {
73 let data = &body[consumed + size..];
74 if let Some(value) = decode_value_only_from_data(data, desc, &decoder) {
75 return Some(value);
76 }
77 }
78 }
79 decode_value_only_from_data(body, desc, &decoder)
80}
81
82fn decode_value_only_from_data(
83 data: &[u8],
84 desc: &StructureDesc,
85 decoder: &PvdDecoder,
86) -> Option<DecodedValue> {
87 let value_field = desc.fields.iter().find(|f| f.name == "value")?;
88 decoder
89 .decode_value(data, &value_field.field_type)
90 .map(|(value, _)| DecodedValue::Structure(vec![("value".to_string(), value)]))
91}
92
93pub fn shift_bitset_left(bitset: &[u8], shift: usize) -> Vec<u8> {
95 if shift == 0 {
96 return bitset.to_vec();
97 }
98 let total_bits = bitset.len() * 8;
99 let new_bits = total_bits + shift;
100 let mut out = vec![0u8; (new_bits + 7) / 8];
101 for bit in 0..total_bits {
102 if (bitset[bit / 8] & (1 << (bit % 8))) != 0 {
103 let new_bit = bit + shift;
104 out[new_bit / 8] |= 1 << (new_bit % 8);
105 }
106 }
107 out
108}
109
110pub fn assemble_segmented_message(first_header: [u8; 8], payloads: Vec<Vec<u8>>) -> Vec<u8> {
113 let mut header = first_header;
114 let is_be = (header[2] & 0x80) != 0;
115 header[2] &= !0x30;
116 let total_len: usize = payloads.iter().map(|p| p.len()).sum();
117 let len_bytes = if is_be {
118 (total_len as u32).to_be_bytes()
119 } else {
120 (total_len as u32).to_le_bytes()
121 };
122 header[4..8].copy_from_slice(&len_bytes);
123 let mut out = header.to_vec();
124 for payload in payloads {
125 out.extend_from_slice(&payload);
126 }
127 out
128}