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