vrt 0.2.3

Parser/encoder for VITA Radio Transport data
Documentation
use rstest::rstest;
use vrt::*;

static VRT_FLEXRADIO_BROADCAST_MSG: &[u8] = &[
    0x38, 0x5f, 0x00, 0x8a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1c, 0x2d, 0x53, 0x4c, 0xff, 0xff,
    0x62, 0x43, 0x8f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63,
    0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x76,
    0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x20, 0x6d,
    0x6f, 0x64, 0x65, 0x6c, 0x3d, 0x46, 0x4c, 0x45, 0x58, 0x2d, 0x36, 0x37, 0x30, 0x30, 0x20, 0x73,
    0x65, 0x72, 0x69, 0x61, 0x6c, 0x3d, 0x31, 0x31, 0x32, 0x31, 0x2d, 0x31, 0x31, 0x30, 0x34, 0x2d,
    0x36, 0x37, 0x30, 0x30, 0x2d, 0x32, 0x39, 0x31, 0x32, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
    0x6e, 0x3d, 0x33, 0x2e, 0x32, 0x2e, 0x33, 0x39, 0x2e, 0x33, 0x33, 0x37, 0x34, 0x20, 0x6e, 0x69,
    0x63, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x50, 0x53, 0x4f, 0x43, 0x32, 0x2f, 0x48, 0x46, 0x2f,
    0x41, 0x4d, 0x50, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x69, 0x67, 0x6e, 0x3d, 0x57, 0x34, 0x42,
    0x52, 0x20, 0x69, 0x70, 0x3d, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x30, 0x2e, 0x31,
    0x31, 0x20, 0x70, 0x6f, 0x72, 0x74, 0x3d, 0x34, 0x39, 0x39, 0x32, 0x20, 0x73, 0x74, 0x61, 0x74,
    0x75, 0x73, 0x3d, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x75,
    0x73, 0x65, 0x5f, 0x69, 0x70, 0x3d, 0x20, 0x69, 0x6e, 0x75, 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x73,
    0x74, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x5f,
    0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x76, 0x33, 0x20, 0x72, 0x61, 0x64, 0x69, 0x6f,
    0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x3d, 0x30, 0x30, 0x2d, 0x31,
    0x43, 0x2d, 0x32, 0x44, 0x2d, 0x30, 0x32, 0x2d, 0x30, 0x46, 0x2d, 0x45, 0x41, 0x20, 0x72, 0x65,
    0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61,
    0x6c, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x3d, 0x30, 0x20, 0x66, 0x70, 0x63, 0x5f,
    0x6d, 0x61, 0x63, 0x3d, 0x20, 0x77, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
    0x65, 0x64, 0x3d, 0x31, 0x20, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x5f, 0x63, 0x6c,
    0x69, 0x65, 0x6e, 0x74, 0x73, 0x3d, 0x32, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
    0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x3d, 0x32, 0x20, 0x6d, 0x61, 0x78, 0x5f,
    0x70, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x70, 0x74, 0x65, 0x72, 0x73, 0x3d, 0x38, 0x20, 0x61, 0x76,
    0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x70, 0x74,
    0x65, 0x72, 0x73, 0x3d, 0x38, 0x20, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x73,
    0x3d, 0x38, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x6c, 0x69,
    0x63, 0x65, 0x73, 0x3d, 0x38, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
    0x5f, 0x69, 0x70, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
    0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65,
    0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x73, 0x3d, 0x20, 0x67, 0x75, 0x69,
    0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
    0x3d, 0x20, 0x67, 0x75, 0x69, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x61, 0x6e,
    0x64, 0x6c, 0x65, 0x73, 0x3d, 0x00, 0x00, 0x00,
];

static VRT_FLEXRADIO_MSG: &[u8] = &[
    0x38, 0x53, 0x1, 0x4, 0x42, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1C, 0x2D, 0x53, 0x4C, 0x80, 0x4, 0x67,
    0xE5, 0x6F, 0x5E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xBB, 0xCA, 0x38, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0xB, 0xB8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50, 0x1, 0xE6, 0x0, 0x1, 0x0,
    0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x9, 0x9C, 0x7, 0xB6, 0x29, 0xFE, 0x29, 0x26, 0x2A, 0x2E,
    0x28, 0x76, 0x27, 0x3E, 0x29, 0x8E, 0x29, 0x4E, 0x29, 0x36, 0x29, 0x7E, 0x28, 0xE6, 0x2A, 0xDE,
    0x28, 0xB6, 0x28, 0x8E, 0x27, 0x16, 0x29, 0xAE, 0x29, 0x1E, 0x29, 0x1E, 0x29, 0x16, 0x2A, 0xA6,
    0x28, 0xE, 0x26, 0x7E, 0x2B, 0x36, 0x27, 0xD6, 0x28, 0xA6, 0x26, 0x7E, 0x2A, 0xE6, 0x28, 0x6E,
    0x26, 0x9E, 0x2A, 0x1E, 0x2A, 0x4E, 0x29, 0x6, 0x2A, 0x4E, 0x28, 0x36, 0x28, 0x2E, 0x27, 0x7E,
    0x27, 0x1E, 0x28, 0x6, 0x28, 0xDE, 0x26, 0x9E, 0x2A, 0xDE, 0x28, 0xE, 0x28, 0xD6, 0x27, 0x16,
    0x29, 0x5E, 0x29, 0x96, 0x29, 0x1E, 0x2B, 0x26, 0x28, 0x5E, 0x28, 0x7E, 0x27, 0x1E, 0x29, 0x76,
    0x2A, 0x9E, 0x26, 0x7E, 0x2A, 0x6, 0x29, 0x36, 0x2B, 0x6, 0x28, 0x2E, 0x28, 0x26, 0x28, 0x66,
    0x28, 0x8E, 0x28, 0x1E, 0x27, 0x7E, 0x27, 0x26, 0x27, 0x2E, 0x28, 0x2E, 0x26, 0xAE, 0x29, 0x66,
    0x2B, 0x1E, 0x28, 0x36, 0x28, 0xC6, 0x27, 0x26, 0x29, 0x5E, 0x29, 0x2E, 0x29, 0xCE, 0x2A, 0x26,
    0x2A, 0x3E, 0x2A, 0x16, 0x29, 0x7E, 0x2A, 0xF6, 0x27, 0xE6, 0x28, 0x26, 0x28, 0xE, 0x27, 0x9E,
    0x27, 0xEE, 0x26, 0xDE, 0x29, 0xD6, 0x29, 0x6E, 0x29, 0x4E, 0x2B, 0x1E, 0x28, 0x5E, 0x28, 0x8E,
    0x26, 0x7E, 0x29, 0xA6, 0x29, 0x2E, 0x2A, 0x7E, 0x28, 0x1E, 0x28, 0x86, 0x28, 0x96, 0x26, 0xCE,
    0x29, 0x2E, 0x2A, 0xAE, 0x28, 0x6, 0x26, 0x86, 0x29, 0x7E, 0x29, 0x9E, 0x28, 0xE6, 0x2B, 0x6,
    0x28, 0xB6, 0x28, 0x96, 0x26, 0xCE, 0x29, 0x66, 0x29, 0xFE, 0x2A, 0x7E, 0x2A, 0x1E, 0x29, 0xE,
    0x2A, 0x86, 0x27, 0xB6, 0x27, 0x9E, 0x28, 0x16, 0x28, 0x96, 0x28, 0x7E, 0x28, 0x6E, 0x28, 0xAE,
    0x26, 0x96, 0x29, 0x4E, 0x29, 0xE6, 0x2A, 0x36, 0x29, 0x7E, 0x2A, 0x8E, 0x28, 0x6E, 0x28, 0xD6,
    0x26, 0xA6, 0x29, 0xA6, 0x29, 0x7E, 0x2B, 0x46, 0x27, 0x6, 0x29, 0x2E, 0x2A, 0xFE, 0x28, 0xAE,
    0x26, 0xE6, 0x29, 0x2E, 0x28, 0xE6, 0x2B, 0x2E, 0x26, 0xAE, 0x29, 0x6, 0x2A, 0xD6, 0x28, 0x9E,
    0x28, 0x2E, 0x28, 0x6, 0x28, 0xBE, 0x28, 0x9E, 0x28, 0x86, 0x28, 0x76, 0x27, 0xC6, 0x27, 0xBE,
    0x27, 0x7E, 0x27, 0x9E, 0x28, 0x56, 0x27, 0xCE, 0x27, 0x86, 0x28, 0x46, 0x26, 0x96, 0x2B, 0x2E,
    0x28, 0xC6, 0x28, 0x96, 0x28, 0x16, 0x28, 0x1E, 0x28, 0x5E, 0x28, 0x4E, 0x27, 0xA6, 0x27, 0x8E,
    0x27, 0x6E, 0x28, 0x8E, 0x26, 0xCE, 0x28, 0xF6, 0x2B, 0x2E, 0x26, 0x96, 0x28, 0xF6, 0x2B, 0x1E,
    0x28, 0xAE, 0x26, 0x7E, 0x29, 0x3E, 0x2A, 0x5E, 0x2A, 0xA6, 0x29, 0xCE, 0x2B, 0x16, 0x28, 0x76,
    0x28, 0x3E, 0x26, 0xDE, 0x29, 0xD6, 0x29, 0x9E, 0x29, 0x8E, 0x29, 0x36, 0x2A, 0xE6, 0x27, 0xFE,
    0x27, 0xD6, 0x27, 0xE6, 0x26, 0xF6, 0x2A, 0x46, 0x29, 0xC6, 0x29, 0xE, 0x2B, 0x6, 0x28, 0x56,
    0x28, 0x26, 0x28, 0x4E, 0x28, 0x96, 0x28, 0x6E, 0x28, 0xC6, 0x27, 0x4E, 0x29, 0xA6, 0x29, 0x36,
    0x29, 0x66, 0x2B, 0xE, 0x28, 0x9E, 0x27, 0x3E, 0x29, 0x66, 0x2A, 0x76, 0x27, 0x6E, 0x27, 0xE6,
    0x28, 0x9E, 0x26, 0xE6, 0x29, 0xF6, 0x29, 0x4E, 0x29, 0x6, 0x29, 0x3E, 0x29, 0xE, 0x29, 0x6,
    0x2A, 0xF6, 0x27, 0xD6, 0x27, 0xA6, 0x28, 0x26, 0x26, 0x8E, 0x2A, 0x7E, 0x27, 0x3E, 0x27, 0xFE,
    0x28, 0xC6, 0x28, 0xAE, 0x28, 0x26, 0x28, 0xE, 0x28, 0x86, 0x28, 0x16, 0x28, 0x4E, 0x26, 0x7E,
    0x29, 0xBE, 0x29, 0x76, 0x29, 0xA6, 0x2A, 0x6, 0x29, 0x96, 0x2A, 0xD6, 0x28, 0x56, 0x27, 0xAE,
    0x26, 0xE6, 0x27, 0x8E, 0x28, 0x2E, 0x28, 0xB6, 0x28, 0xAE, 0x28, 0x5E, 0x28, 0x9E, 0x28, 0x5E,
    0x28, 0x6E, 0x26, 0xD6, 0x29, 0xCE, 0x29, 0x8E, 0x2A, 0xFE, 0x28, 0x16, 0x28, 0xB6, 0x26, 0x86,
    0x2B, 0x26, 0x27, 0x6, 0x28, 0xE6, 0x2A, 0x5E, 0x27, 0xBE, 0x27, 0xD6, 0x28, 0x7E, 0x28, 0x6E,
    0x28, 0x8E, 0x26, 0xEE, 0x29, 0xC6, 0x2A, 0xA6, 0x28, 0xEE, 0x2B, 0xE6, 0x2B, 0x96, 0x2C, 0x46,
    0x28, 0xE6, 0x2A, 0xE6, 0x28, 0x16, 0x27, 0x6, 0x27, 0x26, 0x28, 0x8E, 0x28, 0xDE, 0x26, 0xBE,
    0x29, 0x46, 0x29, 0x56, 0x29, 0xFE, 0x29, 0x86, 0x2A, 0xB6, 0x27, 0xD6, 0x27, 0xEE, 0x27, 0xF6,
    0x28, 0x1E, 0x28, 0x26, 0x28, 0x3E, 0x28, 0xA6, 0x28, 0x9E, 0x28, 0x3E, 0x28, 0x7E, 0x28, 0x56,
    0x28, 0x26, 0x28, 0x96, 0x28, 0xDE, 0x28, 0xDE, 0x28, 0xB6, 0x26, 0x7E, 0x2B, 0x46, 0x28, 0xDE,
    0x28, 0xBE, 0x28, 0x7E, 0x28, 0xAE, 0x26, 0x9E, 0x29, 0x66, 0x29, 0x2E, 0x2B, 0x2E, 0x26, 0x86,
    0x2B, 0x16, 0x26, 0xAE, 0x29, 0xD6, 0x29, 0x2E, 0x2B, 0x6, 0x26, 0xA6, 0x29, 0xA6, 0x29, 0x26,
    0x2A, 0x1E, 0x27, 0xEE, 0x26, 0xA6, 0x29, 0x5E, 0x29, 0x7E, 0x29, 0x6E, 0x28, 0xE6, 0x2B, 0x2E,
    0x28, 0xA6, 0x26, 0x7E, 0x29, 0xA6, 0x29, 0xC6, 0x29, 0x8E, 0x2B, 0x46, 0x28, 0x2E, 0x27, 0xA6,
    0x27, 0xD6, 0x28, 0x86, 0x28, 0xD6, 0x28, 0x5E, 0x28, 0x8E, 0x28, 0x2E, 0x27, 0xA6, 0x28, 0x2E,
    0x28, 0xC6, 0x26, 0x9E, 0x29, 0x2E, 0x29, 0x26, 0x2B, 0x46, 0x26, 0xEE, 0x29, 0x2E, 0x29, 0x2E,
    0x29, 0xF6, 0x2A, 0x9E, 0x29, 0xD6, 0x2A, 0x4E, 0x27, 0xB6, 0x28, 0x46, 0x28, 0x6E, 0x28, 0x9E,
    0x26, 0x8E, 0x29, 0x36, 0x2A, 0xDE, 0x28, 0x7E, 0x28, 0xC6, 0x26, 0xEE, 0x29, 0xD6, 0x29, 0x96,
    0x2A, 0xFE, 0x28, 0x4E, 0x28, 0x1E, 0x28, 0x26, 0x28, 0xA6, 0x26, 0xFE, 0x29, 0x2E, 0x29, 0xE,
    0x29, 0x3E, 0x28, 0xEE, 0x28, 0xFE, 0x29, 0x6E, 0x29, 0xA6, 0x29, 0xC6, 0x29, 0x96, 0x29, 0x4E,
    0x29, 0xA6, 0x29, 0x46, 0x2B, 0x16, 0x28, 0xBE, 0x26, 0xB6, 0x29, 0x36, 0x29, 0x7E, 0x29, 0x3E,
    0x2B, 0x1E, 0x28, 0x96, 0x28, 0x56, 0x26, 0xB6, 0x29, 0x36, 0x2A, 0x6, 0x26, 0xC6, 0x27, 0x3E,
    0x27, 0x96, 0x28, 0x96, 0x28, 0xB6, 0x27, 0xF6, 0x27, 0x46, 0x27, 0x8E, 0x28, 0xE, 0x26, 0xB6,
    0x2A, 0x3E, 0x2A, 0x1E, 0x2A, 0xEE, 0x27, 0x8E, 0x27, 0xEE, 0x28, 0x4E, 0x28, 0x66, 0x26, 0x8E,
    0x28, 0xF6, 0x2A, 0xD6, 0x26, 0xE6, 0x29, 0xF6, 0x29, 0x8E, 0x29, 0x3E, 0x29, 0x16, 0x29, 0x6,
    0x2A, 0xEE, 0x27, 0x7E, 0x27, 0x9E, 0x28, 0x56, 0x27, 0xEE, 0x27, 0xA6, 0x27, 0x86, 0x27, 0x7E,
    0x27, 0x96, 0x27, 0xD6, 0x28, 0xD6, 0x28, 0x9E, 0x28, 0xC6, 0x28, 0xDE, 0x28, 0xB6, 0x26, 0xDE,
    0x2B, 0xE, 0x27, 0xD6, 0x27, 0x6E, 0x28, 0x56, 0x26, 0x9E, 0x29, 0x46, 0x2B, 0x26, 0x28, 0x16,
    0x28, 0xA6, 0x26, 0xF6, 0x29, 0xE6, 0x29, 0x46, 0x29, 0x2E, 0x29, 0x1E, 0x2A, 0xCE, 0x26, 0x7E,
    0x29, 0xAE, 0x28, 0xF6, 0x2B, 0xE, 0x26, 0xD6, 0x2A, 0x6E, 0x2A, 0x5E, 0x29, 0x6E, 0x29, 0x6,
    0x29, 0x6, 0x29, 0xB6, 0x2A, 0x6, 0x2A, 0x16, 0x29, 0x66, 0x28, 0xE6, 0x2B, 0x6, 0x28, 0xD6,
    0x26, 0xBE, 0x28, 0xF6, 0x28, 0xEE, 0x0, 0x0, 0x0, 0x0,
];

static VRT_STATIC_TRAILER_TEST_PATTERN: &[u8] = &[0xAA, 0xAA, 0xAA, 0xAA];

#[test]
fn test_parse_vrt_header() {
    let bytes = &VRT_FLEXRADIO_BROADCAST_MSG[0..4];
    let expected = Header {
        packet_type: PktType::ExtDataWithStream,
        c: true,
        t: false,
        tsi: Tsi::Utc,
        tsf: Tsf::SampleCount,
        packet_count: 15,
        packet_size: 138,
    };
    let (_, res) = Header::parse(bytes).expect("failed to parse header");
    assert_eq!(res, expected);
}

#[test]
fn test_parse_vrt_header_tooshort() {
    let bytes = &VRT_FLEXRADIO_BROADCAST_MSG[0..2];
    let actual_error_bool = Header::parse(bytes).unwrap_err().is_incomplete();
    let expected_error_bool = true;
    assert_eq!(actual_error_bool, expected_error_bool);
}

#[test]
fn test_parse_vrt_trailer() {
    let bytes = &VRT_STATIC_TRAILER_TEST_PATTERN[0..4];
    let expected: Trailer = Trailer {
        calibrated_time_enable: true,
        valid_data_enable: false,
        reference_lock_enable: true,
        agcmgc_enable: false,
        detected_signal_enable: true,
        spectral_inversion_enable: false,
        overrange_enable: true,
        sample_loss_enable: false,
        user_defined_enable_1: true,
        user_defined_enable_2: false,
        user_defined_enable_3: true,
        user_defined_enable_4: false,
        calibrated_time_indicator: true,
        valid_data_indicator: false,
        reference_lock_indicator: true,
        agcmgc_indicator: false,
        detected_signal_indicator: true,
        spectral_inversion_indicator: false,
        overrange_indicator: true,
        sample_loss_indicator: false,
        user_defined_indicator_1: true,
        user_defined_indicator_2: false,
        user_defined_indicator_3: true,
        user_defined_indicator_4: false,
        associated_context_packet_count_enable: true,
        associated_context_packet_count: 42,
    };
    let (_, res) = Trailer::parse(bytes).expect("failed to parse trailer");
    assert_eq!(res, expected);
}

#[test]
fn test_parse_vrt_trailer_tooshort() {
    let bytes = &VRT_STATIC_TRAILER_TEST_PATTERN[0..2];
    let actual_error_bool = Trailer::parse(bytes).unwrap_err().is_incomplete();
    let expected_error_bool = true;
    assert_eq!(actual_error_bool, expected_error_bool);
}

#[test]
fn test_parse_vrt_packet() {
    let bytes = VRT_FLEXRADIO_BROADCAST_MSG;
    let (_, res) = VrtPacket::parse(bytes).expect("failed to parse packet");
    assert_eq!(res.stream_id, Some(2048));
    const FLEX_RADIO_OUI: u32 = 0x001C2D;
    let (oui, info_class_code, packet_class_code) = res
        .class_id
        .map(|v| (v.oui, v.information_class_code, v.packet_class_code))
        .expect("Missing ClassId");
    assert_eq!(oui, FLEX_RADIO_OUI);
    assert_eq!(info_class_code, 0x534c);
    assert_eq!(packet_class_code, 0xffff);
    assert_eq!(res.payload, b"discovery_protocol_version=3.0.0.1 model=FLEX-6700 serial=1121-1104-6700-2912 version=3.2.39.3374 nickname=PSOC2/HF/AMP callsign=W4BR ip=192.168.0.11 port=4992 status=Available inuse_ip= inuse_host= max_licensed_version=v3 radio_license_id=00-1C-2D-02-0F-EA requires_additional_license=0 fpc_mac= wan_connected=1 licensed_clients=2 available_clients=2 max_panadapters=8 available_panadapters=8 max_slices=8 available_slices=8 gui_client_ips= gui_client_hosts= gui_client_programs= gui_client_stations= gui_client_handles=\0\0\0");
}

#[test]
fn test_parse_vrt_fft_packet() {
    let bytes = VRT_FLEXRADIO_MSG;
    let (_, res) = VrtPacket::parse(bytes).expect("failed to parse packet");
    assert_eq!(res.stream_id, Some(0x42000001));
}

#[rstest]
#[case(0, Ok(PktType::IfData))]
#[case(1, Ok(PktType::IfDataWithStream))]
#[case(2, Ok(PktType::ExtData))]
#[case(3, Ok(PktType::ExtDataWithStream))]
#[case(4, Ok(PktType::IfContext))]
#[case(5, Ok(PktType::ExtContext))]
#[case(6, Err(Error::PktType(6)))]
fn parse_pkt_type(#[case] input: u8, #[case] expected: Result<PktType, Error>) {
    let pkt_type = PktType::try_from(input);

    assert_eq!(pkt_type, expected);
}

#[rstest]
#[case(&[0x00], Ok(Tsi::None))]
#[case(&[0x01], Ok(Tsi::Utc))]
#[case(&[0x02], Ok(Tsi::Gps))]
#[case(&[0x03], Ok(Tsi::Other))]
#[case(&[0x04], Err(Error::Tsi(4)))]
fn parse_tsi(#[case] input: &[u8], #[case] expected: Result<Tsi, Error>) {
    let tsi = Tsi::try_from(input[0]);

    assert_eq!(tsi, expected);
}

#[rstest]
#[case(&[0x00], Ok(Tsf::None))]
#[case(&[0x01], Ok(Tsf::SampleCount))]
#[case(&[0x02], Ok(Tsf::RealTime))]
#[case(&[0x03], Ok(Tsf::FreeRunning))]
#[case(&[0x04], Err(Error::Tsf(4)))]
fn parse_tsf(#[case] input: &[u8], #[case] expected: Result<Tsf, Error>) {
    let tsi = Tsf::try_from(input[0]);

    assert_eq!(tsi, expected);
}

#[test]
fn serialize() {
    let (_, mut packet) =
        VrtPacket::parse(VRT_FLEXRADIO_BROADCAST_MSG).expect("failed to parse packet");

    let mut buf = [0u8; 1024];
    let len = packet
        .serialize(&mut buf)
        .expect("failed to serialize packet");

    assert_eq!(&buf[..len], VRT_FLEXRADIO_BROADCAST_MSG);
}