use crate::bitstream::{BitDecode, BitEncode, BitError, CountPrefix, FixedBitLen, Sink, Source};
use crate::field::Bits;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
pub enum WireLen<T> {
#[default]
Auto,
Set(T),
}
impl<T> WireLen<T> {
#[must_use]
pub fn auto() -> Self {
WireLen::Auto
}
#[must_use]
pub fn set(value: T) -> Self {
WireLen::Set(value)
}
#[must_use]
pub fn is_auto(&self) -> bool {
matches!(self, WireLen::Auto)
}
#[must_use]
pub fn get(&self) -> Option<&T> {
match self {
WireLen::Set(v) => Some(v),
WireLen::Auto => None,
}
}
}
impl<T: CountPrefix> WireLen<T> {
#[must_use]
pub fn to_count(&self) -> usize {
match self {
WireLen::Set(v) => v.to_count(),
WireLen::Auto => 0,
}
}
pub fn resolve_count(&self, len: usize) -> Result<Self, BitError> {
match self {
WireLen::Set(v) => Ok(WireLen::Set(*v)),
WireLen::Auto => Ok(WireLen::Set(
T::try_from_count(len).map_err(BitError::from)?,
)),
}
}
}
impl<T: Bits> BitDecode for WireLen<T> {
#[inline]
fn bit_decode<S: Source>(r: &mut S) -> Result<Self, BitError> {
Ok(WireLen::Set(r.read::<T>()?))
}
}
impl<T: Bits> BitEncode for WireLen<T> {
#[inline]
fn bit_encode<K: Sink>(&self, w: &mut K) -> Result<(), BitError> {
match self {
WireLen::Set(v) => w.write(*v),
WireLen::Auto => Err(BitError::convert(
"unresolved `WireLen::Auto`: this field needs a \
`#[bw(auto_len = count(f)|bytes(f))]` (or `#[bin(auto_len(...))]`) directive \
to derive its value, or set it explicitly with `WireLen::set(n)`"
.into(),
w.bit_pos(),
)),
}
}
}
impl<T: Bits> FixedBitLen for WireLen<T> {
const BIT_LEN: u32 = <T as Bits>::BITS;
}
#[cfg(test)]
mod unit {
use super::*;
use crate::bitstream::{BitReader, BitWriter};
#[test]
fn default_is_auto() {
assert_eq!(WireLen::<u16>::default(), WireLen::Auto);
assert!(WireLen::<u16>::auto().is_auto());
assert!(!WireLen::set(5u16).is_auto());
}
#[test]
fn decode_yields_set() {
let mut r = BitReader::new(&[0x12, 0x34]);
let v = WireLen::<u16>::bit_decode(&mut r).unwrap();
assert_eq!(v, WireLen::Set(0x1234));
assert_eq!(v.get(), Some(&0x1234));
assert_eq!(v.to_count(), 0x1234);
}
#[test]
fn encode_set_writes_the_value_auto_errors() {
let mut w = BitWriter::new();
WireLen::set(0xABCDu16).bit_encode(&mut w).unwrap();
assert_eq!(w.into_bytes(), [0xAB, 0xCD]);
let mut w = BitWriter::new();
assert!(WireLen::<u16>::auto().bit_encode(&mut w).is_err());
}
#[test]
fn resolve_count_fills_auto_leaves_set_and_checks_overflow() {
assert_eq!(
WireLen::<u16>::auto().resolve_count(7).unwrap(),
WireLen::Set(7)
);
assert_eq!(
WireLen::set(9u16).resolve_count(7).unwrap(),
WireLen::Set(9)
); assert!(WireLen::<u8>::auto().resolve_count(300).is_err());
}
#[test]
fn fixed_bit_len_matches_the_inner_width() {
assert_eq!(<WireLen<u16> as FixedBitLen>::BIT_LEN, 16);
assert_eq!(<WireLen<u32> as FixedBitLen>::BIT_LEN, 32);
}
}