#![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)]
enum SignalStrength {
None,
Weak,
Good,
Excellent,
}
impl DecodeValue<&[u8]> for SignalStrength {
fn decode_value(input: &mut &[u8]) -> tinyklv::Result<Self> {
match decb::u8(input)? {
0 => Ok(SignalStrength::None),
1 => Ok(SignalStrength::Weak),
2 => Ok(SignalStrength::Good),
3 => Ok(SignalStrength::Excellent),
_ => Err(winnow::error::ParserError::from_input(input)),
}
}
}
impl EncodeValue<Vec<u8>> for SignalStrength {
fn encode_value(&self) -> Vec<u8> {
encb::u8(match self {
SignalStrength::None => 0,
SignalStrength::Weak => 1,
SignalStrength::Good => 2,
SignalStrength::Excellent => 3,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum NetworkMode {
Offline,
WiFi,
Cellular,
Satellite,
}
impl DecodeValue<&[u8]> for NetworkMode {
fn decode_value(input: &mut &[u8]) -> tinyklv::Result<Self> {
match decb::u8(input)? {
0 => Ok(NetworkMode::Offline),
1 => Ok(NetworkMode::WiFi),
2 => Ok(NetworkMode::Cellular),
3 => Ok(NetworkMode::Satellite),
_ => Err(winnow::error::ParserError::from_input(input)),
}
}
}
impl EncodeValue<Vec<u8>> for NetworkMode {
fn encode_value(&self) -> Vec<u8> {
encb::u8(match self {
NetworkMode::Offline => 0,
NetworkMode::WiFi => 1,
NetworkMode::Cellular => 2,
NetworkMode::Satellite => 3,
})
}
}
#[derive(Klv, Debug, PartialEq)]
#[klv(
stream = &[u8],
key(dec = decb::u8, enc = encb::u8),
len(dec = decb::u8_as_usize, enc = encb::u8_from_usize),
default(
typ = SignalStrength,
dec = SignalStrength::decode_value,
enc = SignalStrength::encode_value,
),
default(
typ = NetworkMode,
dec = NetworkMode::decode_value,
enc = NetworkMode::encode_value,
),
)]
struct RadioConfig {
#[klv(key = 0x01)]
uplink_signal: SignalStrength,
#[klv(key = 0x02)]
downlink_signal: SignalStrength,
#[klv(key = 0x03)]
mode: NetworkMode,
#[klv(
key = 0x04,
dec = decb::be_u16,
enc = *encb::be_u16,
default = 1_u16,
)]
channel: u16,
}
fn main() {
let original = RadioConfig {
uplink_signal: SignalStrength::Good,
downlink_signal: SignalStrength::Excellent,
mode: NetworkMode::Satellite,
channel: 14,
};
let encoded = original.encode_value();
let decoded = RadioConfig::decode_value(
&mut encoded.as_slice(),
).unwrap();
assert_eq!(decoded, original);
let partial = [
0x01, 0x01, 0x01,
0x02, 0x01, 0x02,
0x03, 0x01, 0x01,
];
let dec_partial = RadioConfig::decode_value(
&mut partial.as_slice(),
).unwrap();
assert_eq!(dec_partial.uplink_signal, SignalStrength::Weak);
assert_eq!(dec_partial.downlink_signal, SignalStrength::Good);
assert_eq!(dec_partial.mode, NetworkMode::WiFi);
assert_eq!(dec_partial.channel, 1, "absent key yields default value");
}