1use crate::{
2 DecodeWithMetadataResult, DecodedVtx, VtxFormatError, VTX_PREFIX, VTX_VERSION_V1,
3 VTX_VERSION_V2,
4};
5
6pub fn decode(bytes: &[u8]) -> Result<(u8, &[u8]), VtxFormatError> {
8 let decoded = decode_with_metadata(bytes)?;
9 Ok((decoded.version, decoded.component))
10}
11
12pub fn decode_with_metadata(bytes: &[u8]) -> DecodeWithMetadataResult<'_> {
14 if bytes.len() < 4 {
15 return Err(VtxFormatError::TooShort);
16 }
17 if bytes[0..3] != VTX_PREFIX {
18 return Err(VtxFormatError::InvalidPrefix);
19 }
20
21 let version = bytes[3];
22 match version {
23 VTX_VERSION_V1 => Ok(DecodedVtx {
24 version,
25 metadata: None,
26 component: &bytes[4..],
27 }),
28 VTX_VERSION_V2 => {
29 let (meta, component) = decode_v2_parts(bytes)?;
30 Ok(DecodedVtx {
31 version,
32 metadata: Some(meta),
33 component,
34 })
35 }
36 other => Err(VtxFormatError::UnsupportedVersion(other)),
37 }
38}
39
40fn decode_v2_parts(bytes: &[u8]) -> Result<(&[u8], &[u8]), VtxFormatError> {
41 if bytes.len() < 8 {
42 return Err(VtxFormatError::TooShort);
43 }
44 let meta_len = u32::from_le_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]) as usize;
45 let meta_start = 8usize;
46 let meta_end = meta_start.saturating_add(meta_len);
47 if meta_end > bytes.len() {
48 return Err(VtxFormatError::InvalidMetadataLength);
49 }
50 Ok((&bytes[meta_start..meta_end], &bytes[meta_end..]))
51}