#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(clippy::unwrap_used)]
use tinyklv::prelude::*; use tinyklv::dec::binary as decb; use tinyklv::enc::binary as encb;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Status {
Idle,
Active,
Error,
Unknown,
}
fn status_from_u8(v: u8) -> Status {
match v {
0 => Status::Idle,
1 => Status::Active,
2 => Status::Error,
_ => Status::Unknown,
}
}
fn enc_status(s: &Status) -> Vec<u8> {
let byte = match s {
Status::Idle => 0,
Status::Active => 1,
Status::Error => 2,
Status::Unknown => 0xFF,
};
encb::u8(byte)
}
#[derive(Klv, Debug, PartialEq, Eq)]
#[klv(
stream = &[u8],
sentinel = b"DEVICE",
key(dec = decb::u8, enc = encb::u8),
len(dec = decb::u8_as_usize, enc = encb::u8_from_usize),
)]
struct Device {
#[klv(
key = 0x01,
dec = decb::u8,
latebind = status_from_u8,
enc = enc_status,
)]
status: Status,
}
const GLOBAL_Z: f32 = 15.0;
#[derive(Debug, Clone, Copy, PartialEq)]
struct Coordinate {
x: f32,
y: f32,
z: f32,
}
fn dec_xy_z0(input: &mut &[u8]) -> tinyklv::Result<Coordinate> {
let x = decb::be_f32(input)?;
let y = decb::be_f32(input)?;
Ok(Coordinate { x, y, z: 0.0 })
}
fn enc_xyz(c: &Coordinate) -> Vec<u8> {
let mut out = encb::be_f32(c.x);
out.extend(encb::be_f32(c.y));
out
}
fn apply_global_z(c: &mut Coordinate) {
c.z = GLOBAL_Z;
}
#[derive(Klv, Debug, PartialEq)]
#[klv(
stream = &[u8],
sentinel = b"TELEMETRY",
key(dec = decb::u8, enc = encb::u8),
len(dec = decb::u8_as_usize, enc = encb::u8_from_usize),
)]
struct Telemetry {
#[klv(
key = 0x01,
dec = dec_xy_z0,
latebind = &mut apply_global_z,
enc = enc_xyz,
)]
position: Coordinate,
}
fn main() {
let device = Device { status: Status::Active };
let frame = device.encode_frame();
let decoded = Device::decode_frame(
&mut frame.as_slice(),
).unwrap();
assert_eq!(decoded.status, Status::Active);
let tele = Telemetry {
position: Coordinate { x: 1.5, y: 2.5, z: 0.0 },
};
let frame = tele.encode_frame();
let decoded = Telemetry::decode_frame(
&mut frame.as_slice(),
).unwrap();
assert_eq!(decoded.position.x, 1.5);
assert_eq!(decoded.position.y, 2.5);
assert_eq!(decoded.position.z, GLOBAL_Z);
}