use std::borrow::Cow;
use std::fmt;
use std::mem::size_of;
use heed::BoxedError;
use heed::byteorder::{BigEndian, ByteOrder};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Version {
pub major: u32,
pub minor: u32,
pub patch: u32,
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
}
}
impl Version {
pub fn compatible_with_current_for_build(&self) -> bool {
let current = Version::default();
self == ¤t
}
}
impl Default for Version {
fn default() -> Self {
Version {
major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(),
minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(),
patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(),
}
}
}
pub enum VersionCodec {}
impl<'a> heed::BytesEncode<'a> for VersionCodec {
type EItem = Version;
fn bytes_encode(item: &'a Self::EItem) -> Result<Cow<'a, [u8]>, BoxedError> {
let Version {
major,
minor,
patch,
} = item;
let mut output = Vec::with_capacity(size_of::<u32>() * 3);
output.extend_from_slice(&major.to_be_bytes());
output.extend_from_slice(&minor.to_be_bytes());
output.extend_from_slice(&patch.to_be_bytes());
Ok(Cow::Owned(output))
}
}
impl heed::BytesDecode<'_> for VersionCodec {
type DItem = Version;
fn bytes_decode(bytes: &'_ [u8]) -> Result<Self::DItem, BoxedError> {
let major = BigEndian::read_u32(bytes);
let bytes = &bytes[size_of_val(&major)..];
let minor = BigEndian::read_u32(bytes);
let bytes = &bytes[size_of_val(&minor)..];
let patch = BigEndian::read_u32(bytes);
Ok(Version {
major,
minor,
patch,
})
}
}
#[cfg(test)]
mod test {
use heed::{BytesDecode, BytesEncode};
use super::*;
#[test]
fn version_codec() {
let version = Version {
major: 0,
minor: 10,
patch: 100,
};
let encoded = VersionCodec::bytes_encode(&version).unwrap();
let decoded = VersionCodec::bytes_decode(&encoded).unwrap();
assert_eq!(version.major, decoded.major);
assert_eq!(version.minor, decoded.minor);
assert_eq!(version.patch, decoded.patch);
}
}