vecdb/
version.rs

1use std::{
2    fs,
3    io::{self, Read},
4    iter::Sum,
5    ops::Add,
6    path::Path,
7};
8
9use allocative::Allocative;
10use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
11
12use crate::{Error, Result};
13
14#[derive(
15    Allocative,
16    Default,
17    Debug,
18    Clone,
19    Copy,
20    PartialEq,
21    Eq,
22    PartialOrd,
23    Ord,
24    FromBytes,
25    IntoBytes,
26    Immutable,
27    KnownLayout,
28)]
29pub struct Version(u64);
30
31impl Version {
32    pub const ZERO: Self = Self(0);
33    pub const ONE: Self = Self(1);
34    pub const TWO: Self = Self(2);
35
36    pub const fn new(v: u64) -> Self {
37        Self(v)
38    }
39
40    pub fn write(&self, path: &Path) -> Result<(), io::Error> {
41        fs::write(path, self.as_bytes())
42    }
43
44    pub fn swap_bytes(self) -> Self {
45        Self(self.0.swap_bytes())
46    }
47
48    ///
49    /// Ok(true) if existed and is same.
50    ///
51    /// Ok(false) if didn't exist.
52    ///
53    pub fn validate(&self, path: &Path) -> Result<bool> {
54        if let Ok(prev_version) = Version::try_from(path) {
55            if prev_version != *self {
56                if prev_version.swap_bytes() == *self {
57                    return Err(Error::WrongEndian);
58                }
59                return Err(Error::DifferentVersion {
60                    found: prev_version,
61                    expected: *self,
62                });
63            }
64
65            Ok(true)
66        } else {
67            Ok(false)
68        }
69    }
70}
71
72impl From<Version> for u64 {
73    fn from(value: Version) -> u64 {
74        value.0
75    }
76}
77
78impl From<u64> for Version {
79    fn from(value: u64) -> Self {
80        Self(value)
81    }
82}
83
84impl TryFrom<&Path> for Version {
85    type Error = Error;
86    fn try_from(value: &Path) -> Result<Self, Self::Error> {
87        let mut buf = [0; 8];
88        fs::read(value)?.as_slice().read_exact(&mut buf)?;
89        Ok(*(Self::ref_from_bytes(&buf)?))
90    }
91}
92
93impl Add<Version> for Version {
94    type Output = Self;
95    fn add(self, rhs: Version) -> Self::Output {
96        Self(self.0 + rhs.0)
97    }
98}
99
100impl Sum for Version {
101    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
102        iter.fold(Self::ZERO, Add::add)
103    }
104}