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 Ok((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 Ok((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).ok()?;
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 .ok()
62 .map(|(value, _)| value)
63 .filter(|value| !decoded_is_empty(value))
64}
65
66fn decode_put_body_value_only(
67 body: &[u8],
68 desc: &StructureDesc,
69 is_be: bool,
70) -> Option<DecodedValue> {
71 let decoder = PvdDecoder::new(is_be);
72 if let Ok((size, consumed)) = decoder.decode_size(body) {
73 if consumed + size <= body.len() {
74 let data = &body[consumed + size..];
75 if let Some(value) = decode_value_only_from_data(data, desc, &decoder) {
76 return Some(value);
77 }
78 }
79 }
80 decode_value_only_from_data(body, desc, &decoder)
81}
82
83fn decode_value_only_from_data(
84 data: &[u8],
85 desc: &StructureDesc,
86 decoder: &PvdDecoder,
87) -> Option<DecodedValue> {
88 let value_field = desc.fields.iter().find(|f| f.name == "value")?;
89 decoder
90 .decode_value(data, &value_field.field_type)
91 .ok()
92 .map(|(value, _)| DecodedValue::Structure(vec![("value".to_string(), value)]))
93}
94
95pub fn shift_bitset_left(bitset: &[u8], shift: usize) -> Vec<u8> {
97 if shift == 0 {
98 return bitset.to_vec();
99 }
100 let total_bits = bitset.len() * 8;
101 let new_bits = total_bits + shift;
102 let mut out = vec![0u8; (new_bits + 7) / 8];
103 for bit in 0..total_bits {
104 if (bitset[bit / 8] & (1 << (bit % 8))) != 0 {
105 let new_bit = bit + shift;
106 out[new_bit / 8] |= 1 << (new_bit % 8);
107 }
108 }
109 out
110}