vtx_format/
lib.rs

1//! vtx-format:统一定义 .vtx 包格式(编码/解码)
2//!
3//! v1 格式:
4//! - Header: 4 bytes = b"VTX\x01"
5//! - Payload: component bytes (WebAssembly Component)
6
7use thiserror::Error;
8
9pub const VTX_PREFIX: [u8; 3] = [0x56, 0x54, 0x58]; // "VTX"
10pub const VTX_VERSION_V1: u8 = 0x01;
11pub const VTX_MAGIC_V1: [u8; 4] = [VTX_PREFIX[0], VTX_PREFIX[1], VTX_PREFIX[2], VTX_VERSION_V1];
12
13#[derive(Debug, Error)]
14pub enum VtxFormatError {
15    #[error("vtx file too short")]
16    TooShort,
17
18    #[error("invalid vtx prefix (expected 'VTX')")]
19    InvalidPrefix,
20
21    #[error("unsupported vtx version: {0}")]
22    UnsupportedVersion(u8),
23}
24
25/// 编码 v1:VTX_MAGIC_V1 + component bytes
26pub fn encode_v1(component_bytes: &[u8]) -> Vec<u8> {
27    let mut out = Vec::with_capacity(VTX_MAGIC_V1.len() + component_bytes.len());
28    out.extend_from_slice(&VTX_MAGIC_V1);
29    out.extend_from_slice(component_bytes);
30    out
31}
32
33/// 解码:返回 (version, component_bytes_slice)
34pub fn decode(bytes: &[u8]) -> Result<(u8, &[u8]), VtxFormatError> {
35    if bytes.len() < 4 {
36        return Err(VtxFormatError::TooShort);
37    }
38    if bytes[0..3] != VTX_PREFIX {
39        return Err(VtxFormatError::InvalidPrefix);
40    }
41
42    let version = bytes[3];
43    match version {
44        VTX_VERSION_V1 => Ok((version, &bytes[4..])),
45        other => Err(VtxFormatError::UnsupportedVersion(other)),
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_encode_v1_structure() {
55        let payload = b"wasm-magic";
56        let encoded = encode_v1(payload);
57
58        // 验证头部魔数
59        assert_eq!(&encoded[0..4], &VTX_MAGIC_V1);
60        // 验证负载内容
61        assert_eq!(&encoded[4..], payload);
62    }
63
64    #[test]
65    fn test_decode_valid_v1() {
66        let payload = b"component-data";
67        let mut data = Vec::new();
68        data.extend_from_slice(&VTX_MAGIC_V1);
69        data.extend_from_slice(payload);
70
71        let result = decode(&data);
72        assert!(result.is_ok());
73        let (version, body) = result.unwrap();
74
75        assert_eq!(version, VTX_VERSION_V1);
76        assert_eq!(body, payload);
77    }
78
79    #[test]
80    fn test_decode_too_short() {
81        let data = b"VTX"; // 只有 3 字节
82        let result = decode(data);
83        assert!(matches!(result, Err(VtxFormatError::TooShort)));
84    }
85
86    #[test]
87    fn test_decode_invalid_prefix() {
88        // 错误的头部:VTY\x01
89        let data = b"VTY\x01payload";
90        let result = decode(data);
91        assert!(matches!(result, Err(VtxFormatError::InvalidPrefix)));
92    }
93
94    #[test]
95    fn test_decode_unsupported_version() {
96        // 版本号为 0x02
97        let data = b"VTX\x02payload";
98        let result = decode(data);
99
100        if let Err(VtxFormatError::UnsupportedVersion(v)) = result {
101            assert_eq!(v, 2);
102        } else {
103            panic!("Should return UnsupportedVersion error");
104        }
105    }
106}