diff --git a/Cargo.toml b/Cargo.toml index 18ad832..0d1cc64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "versioned-binary-serialization" -version = "0.1.0" +version = "0.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/bincode_serializer.rs b/src/bincode_serializer.rs index 72848bb..ac3d397 100644 --- a/src/bincode_serializer.rs +++ b/src/bincode_serializer.rs @@ -1,15 +1,17 @@ -use std::io::Write; +use std::{io::Write, marker::PhantomData}; -use crate::{binary_serializer::BinarySerializer, version::Version, versioned::Versioned}; +use crate::{ + binary_serializer::BinarySerializer, + version::{StaticVersionType, Version}, + versioned::Versioned, +}; use anyhow::{anyhow, Result}; use serde::{Deserialize, Serialize}; -pub struct BincodeSerializer; -impl BinarySerializer - for BincodeSerializer -{ - const MAJOR: u16 = VER_MAJOR; - const MINOR: u16 = VER_MINOR; +pub struct BincodeSerializer(PhantomData); +impl BinarySerializer for BincodeSerializer { + const MAJOR: u16 = VER::MAJOR; + const MINOR: u16 = VER::MINOR; fn serialize_no_version(value: &T) -> Result> where T: Serialize, @@ -38,7 +40,7 @@ impl BinarySerializer T: Deserialize<'a>, { let (ver, rest) = Version::deserialize(bytes)?; - if ver.major != VER_MAJOR || ver.minor != VER_MINOR { + if ver.major != VER::MAJOR || ver.minor != VER::MINOR { return Err(anyhow!( "Version Mismatch! Expected {}, got {}", ver, @@ -50,16 +52,15 @@ impl BinarySerializer } // Testing; will use to replace BincodeSerializer after applying `Versioned` to existing serialized types -pub struct VersionChecker { - _phantom: std::marker::PhantomData, +pub struct VersionChecker { + _phantom_ver: std::marker::PhantomData, + _phantom_type: std::marker::PhantomData, } -impl - VersionChecker -{ - pub const VERSION_MISMATCH: () = if VER_MAJOR < TYPE::MIN_MAJOR - || VER_MAJOR > TYPE::MAX_MAJOR - || (VER_MAJOR == TYPE::MIN_MAJOR && VER_MINOR < TYPE::MIN_MINOR) - || (VER_MAJOR == TYPE::MAX_MAJOR && VER_MINOR > TYPE::MAX_MINOR) +impl VersionChecker { + pub const VERSION_MISMATCH: () = if VER::MAJOR < TYPE::MIN_MAJOR + || VER::MAJOR > TYPE::MAX_MAJOR + || (VER::MAJOR == TYPE::MIN_MAJOR && VER::MINOR < TYPE::MIN_MINOR) + || (VER::MAJOR == TYPE::MAX_MAJOR && VER::MINOR > TYPE::MAX_MINOR) { panic!("unsupported type for version") }; @@ -68,6 +69,7 @@ impl pub trait VersionedBinarySerializer { const MAJOR: u16; const MINOR: u16; + type StaticVersion: StaticVersionType; fn version() -> Version { Version { @@ -95,19 +97,18 @@ pub trait VersionedBinarySerializer { T: Deserialize<'a> + Versioned; } -pub struct VersionedBincodeSerializer; -impl VersionedBinarySerializer - for VersionedBincodeSerializer -{ - const MAJOR: u16 = VER_MAJOR; - const MINOR: u16 = VER_MINOR; +pub struct VersionedBincodeSerializer(PhantomData); +impl VersionedBinarySerializer for VersionedBincodeSerializer { + const MAJOR: u16 = VER::MAJOR; + const MINOR: u16 = VER::MINOR; + type StaticVersion = VER; fn serialize_no_version(value: &T) -> Result> where T: Serialize + Versioned, { #[allow(clippy::let_unit_value)] - let _ = VersionChecker::::VERSION_MISMATCH; + let _ = VersionChecker::::VERSION_MISMATCH; Ok(bincode::serialize(value)?) } @@ -117,7 +118,7 @@ impl VersionedBinarySerializer T: Deserialize<'a> + Versioned, { #[allow(clippy::let_unit_value)] - let _ = VersionChecker::::VERSION_MISMATCH; + let _ = VersionChecker::::VERSION_MISMATCH; Ok(bincode::deserialize(bytes)?) } @@ -127,7 +128,7 @@ impl VersionedBinarySerializer T: Serialize + Versioned, { #[allow(clippy::let_unit_value)] - let _ = VersionChecker::::VERSION_MISMATCH; + let _ = VersionChecker::::VERSION_MISMATCH; let mut vec = Self::version().serialize(); bincode::serialize_into(vec.by_ref(), value)?; @@ -139,10 +140,10 @@ impl VersionedBinarySerializer T: Deserialize<'a> + Versioned, { #[allow(clippy::let_unit_value)] - let _ = VersionChecker::::VERSION_MISMATCH; + let _ = VersionChecker::::VERSION_MISMATCH; let (ver, rest) = Version::deserialize(bytes)?; - if ver.major != VER_MAJOR || ver.minor != VER_MINOR { + if ver.major != VER::MAJOR || ver.minor != VER::MINOR { return Err(anyhow!( "Version Mismatch! Expected {}, got {}", ver, @@ -157,17 +158,19 @@ impl VersionedBinarySerializer mod test { use serde::{Deserialize, Serialize}; - use crate::{binary_serializer::BinarySerializer, version::Version}; + use crate::{ + binary_serializer::BinarySerializer, + version::{StaticVersion, Version}, + versioned::Versioned, + }; use super::{BincodeSerializer, VersionedBinarySerializer, VersionedBincodeSerializer}; mod version_0_1 { - use crate::versioned::Versioned; - use super::*; - pub type Serializer = BincodeSerializer<0u16, 1u16>; - pub type VSerializer = VersionedBincodeSerializer<0u16, 1u16>; + pub type Serializer = BincodeSerializer>; + pub type VSerializer = VersionedBincodeSerializer>; #[derive(Serialize, Deserialize)] pub struct Thing { @@ -187,19 +190,17 @@ mod test { mod version_0_2 { use super::*; - pub type Serializer = BincodeSerializer<0u16, 2u16>; - pub type VSerializer = VersionedBincodeSerializer<0u16, 2u16>; + pub type Serializer = BincodeSerializer>; + pub type VSerializer = VersionedBincodeSerializer>; pub type Thing = version_0_1::Thing; } mod version_0_3 { - use crate::versioned::Versioned; - use super::*; - pub type Serializer = BincodeSerializer<0u16, 3u16>; - pub type VSerializer = VersionedBincodeSerializer<0u16, 3u16>; + pub type Serializer = BincodeSerializer>; + pub type VSerializer = VersionedBincodeSerializer>; #[derive(Serialize, Deserialize)] pub struct Thing { diff --git a/src/version.rs b/src/version.rs index 1d752b2..592152a 100644 --- a/src/version.rs +++ b/src/version.rs @@ -34,12 +34,31 @@ impl Version { } } +pub trait StaticVersionType: Clone + Copy + Debug + private::Sealed { + const MAJOR: u16; + const MINOR: u16; + + fn version() -> Version { + Version { + major: Self::MAJOR, + minor: Self::MINOR, + } + } +} + #[derive(Clone, Copy, Display)] pub struct StaticVersion; -impl StaticVersion { - pub const MAJOR: u16 = MAJOR; - pub const MINOR: u16 = MINOR; +impl StaticVersionType for StaticVersion { + const MAJOR: u16 = MAJOR; + const MINOR: u16 = MINOR; + + fn version() -> Version { + Version { + major: Self::MAJOR, + minor: Self::MINOR, + } + } } impl Debug for StaticVersion { @@ -50,3 +69,10 @@ impl Debug for StaticVersion { .finish() } } + +mod private { + pub trait Sealed {} + + // Implement for those same types, but no others. + impl Sealed for super::StaticVersion {} +}