use crate::coding::{Decode, DecodeError, Encode, EncodeError, VarInt};
use std::fmt;
use std::ops::Deref;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version(pub u32);
impl Version {
pub const DRAFT_11: Version = Version(0xff00000b);
pub const DRAFT_12: Version = Version(0xff00000c);
pub const DRAFT_13: Version = Version(0xff00000d);
pub const DRAFT_14: Version = Version(0xff00000e);
}
impl From<u32> for Version {
fn from(v: u32) -> Self {
Self(v)
}
}
impl From<Version> for u32 {
fn from(v: Version) -> Self {
v.0
}
}
impl Decode for Version {
fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
let v = VarInt::decode(r)?;
Ok(Self(u32::try_from(v).map_err(DecodeError::BoundsExceeded)?))
}
}
impl Encode for Version {
fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
VarInt::from_u32(self.0).encode(w)?;
Ok(())
}
}
impl fmt::Debug for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{self}")
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0 > 0xff000000 {
write!(f, "DRAFT_{:02}", self.0 & 0x00ffffff)
} else {
self.0.fmt(f)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Versions(pub Vec<Version>);
impl Decode for Versions {
fn decode<R: bytes::Buf>(r: &mut R) -> Result<Self, DecodeError> {
let count = usize::decode(r)?;
let mut vs = Vec::new();
for _ in 0..count {
let v = Version::decode(r)?;
vs.push(v);
}
Ok(Self(vs))
}
}
impl Encode for Versions {
fn encode<W: bytes::BufMut>(&self, w: &mut W) -> Result<(), EncodeError> {
self.0.len().encode(w)?;
for v in &self.0 {
v.encode(w)?;
}
Ok(())
}
}
impl Deref for Versions {
type Target = Vec<Version>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<Vec<Version>> for Versions {
fn from(vs: Vec<Version>) -> Self {
Self(vs)
}
}
impl<const N: usize> From<[Version; N]> for Versions {
fn from(vs: [Version; N]) -> Self {
Self(vs.to_vec())
}
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
#[test]
fn encode_decode() {
let mut buf = BytesMut::new();
let versions = Versions(vec![Version(1), Version::DRAFT_12, Version::DRAFT_13]);
versions.encode(&mut buf).unwrap();
#[rustfmt::skip]
assert_eq!(
buf.to_vec(),
vec![
0x03, 0x01,
0xC0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0C,
0xC0, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0D,
]
);
let decoded = Versions::decode(&mut buf).unwrap();
assert_eq!(decoded, versions);
}
}