1use std::ffi::{OsStr, OsString};
2
3use crate::synchronizer::SynchronizerError;
4use crate::synchronizer::SynchronizerError::*;
5
6#[derive(Clone, Copy, Debug, PartialEq)]
11pub struct InstanceVersion(pub(crate) u64);
12
13const DATA_SIZE_BITS: usize = 39;
14const DATA_CHECKSUM_BITS: usize = 24;
15
16impl InstanceVersion {
17 #[inline]
19 pub(crate) fn new(
20 idx: usize,
21 size: usize,
22 checksum: u64,
23 ) -> Result<InstanceVersion, SynchronizerError> {
24 let mut res: u64 = 0;
25
26 if idx > 1 || size >= 1 << DATA_SIZE_BITS {
27 return Err(InvalidInstanceVersionParams);
28 }
29
30 res |= (idx as u64) & 1;
31 res |= ((size as u64) & ((1 << DATA_SIZE_BITS) - 1)) << 1;
32 res |= (checksum & ((1 << DATA_CHECKSUM_BITS) - 1)) << (DATA_SIZE_BITS + 1);
33
34 Ok(InstanceVersion(res))
35 }
36
37 #[inline]
39 pub(crate) fn idx(&self) -> usize {
40 self.0 as usize & 1
41 }
42
43 #[inline]
45 pub(crate) fn size(&self) -> usize {
46 (self.0 as usize >> 1) & ((1 << DATA_SIZE_BITS) - 1)
47 }
48
49 #[cfg(test)]
51 pub(crate) fn checksum(&self) -> u64 {
52 self.0 >> (DATA_SIZE_BITS + 1)
53 }
54
55 #[inline]
57 pub(crate) fn path(&self, path_prefix: &OsStr) -> OsString {
58 let mut path = path_prefix.to_os_string();
59 path.push(format!("_data_{}", self.idx()));
60 path
61 }
62}
63
64impl TryFrom<u64> for InstanceVersion {
65 type Error = SynchronizerError;
66
67 #[inline]
69 fn try_from(v: u64) -> Result<InstanceVersion, Self::Error> {
70 if v == 0 {
71 Err(UninitializedState)
72 } else {
73 Ok(InstanceVersion(v))
74 }
75 }
76}
77
78impl From<InstanceVersion> for u64 {
79 #[inline]
81 fn from(v: InstanceVersion) -> Self {
82 v.0
83 }
84}
85
86#[cfg(test)]
87mod tests {
88 use crate::instance::*;
89 use proptest::prelude::*;
90
91 proptest! {
92 #[test]
93 fn test_new(idx in 0..2usize, size in 0..1usize << DATA_SIZE_BITS, checksum in 0..u64::MAX) {
94 let v = InstanceVersion::new(idx, size, checksum).unwrap();
95
96 assert_eq!(idx, v.idx());
97 assert_eq!(size, v.size());
98 assert_eq!(checksum & ((1 << DATA_CHECKSUM_BITS) - 1), v.checksum());
99 }
100 }
101}