use crate::error::{ProtocolError, Result};
pub const PROTOCOL_VERSION: u32 = 1;
pub const MIN_PROTOCOL_VERSION: u32 = 1;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ProtocolVersion(u32);
impl ProtocolVersion {
pub fn new(version: u32) -> Self {
Self(version)
}
pub fn version(&self) -> u32 {
self.0
}
pub fn is_compatible(&self) -> bool {
self.0 >= MIN_PROTOCOL_VERSION && self.0 <= PROTOCOL_VERSION
}
pub fn validate(&self) -> Result<()> {
if self.is_compatible() {
Ok(())
} else {
Err(ProtocolError::UnsupportedProtocolVersion {
actual: self.0,
expected: PROTOCOL_VERSION,
})
}
}
}
impl From<u32> for ProtocolVersion {
fn from(version: u32) -> Self {
Self(version)
}
}
impl From<ProtocolVersion> for u32 {
fn from(version: ProtocolVersion) -> Self {
version.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_current_version_is_compatible() {
let version = ProtocolVersion::new(PROTOCOL_VERSION);
assert!(version.is_compatible());
assert!(version.validate().is_ok());
}
#[test]
fn test_v1_is_still_compatible() {
let version = ProtocolVersion::new(1);
assert!(version.is_compatible());
assert!(version.validate().is_ok());
}
#[test]
fn test_incompatible_version() {
let version = ProtocolVersion::new(999);
assert!(!version.is_compatible());
assert!(version.validate().is_err());
}
#[test]
fn test_version_zero_incompatible() {
let version = ProtocolVersion::new(0);
assert!(!version.is_compatible());
assert!(version.validate().is_err());
}
#[test]
fn test_version_conversion() {
let v1 = ProtocolVersion::from(42);
assert_eq!(v1.version(), 42);
let v2: u32 = v1.into();
assert_eq!(v2, 42);
}
#[test]
fn test_version_error_message() {
let version = ProtocolVersion::new(5);
let result = version.validate();
assert!(result.is_err());
let err = result.unwrap_err();
let msg = err.to_string();
assert!(msg.contains("5"));
assert!(msg.contains(&PROTOCOL_VERSION.to_string()));
}
}