Skip to main content

vecdb/
version.rs

1use std::{
2    fs,
3    io::{self, Read},
4    iter::Sum,
5    ops::Add,
6    path::Path,
7};
8
9use crate::{Bytes, Error, Result, SIZE_OF_U64};
10
11/// Version tracking for data schema and computed values.
12///
13/// Used to detect when stored data needs to be recomputed due to changes
14/// in computation logic or source data versions. Supports validation
15/// against persisted versions to ensure compatibility.
16#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17#[must_use = "Version values should be used for compatibility checks"]
18pub struct Version(u64);
19
20impl Version {
21    pub const ZERO: Self = Self(0);
22    pub const ONE: Self = Self(1);
23    pub const TWO: Self = Self(2);
24
25    pub const fn new(v: u64) -> Self {
26        Self(v)
27    }
28
29    pub fn write(&self, path: &Path) -> Result<(), io::Error> {
30        fs::write(path, self.to_bytes().as_ref())
31    }
32
33    pub fn swap_bytes(self) -> Self {
34        Self(self.0.swap_bytes())
35    }
36}
37
38impl Bytes for Version {
39    type Array = [u8; size_of::<Self>()];
40
41    #[inline]
42    fn to_bytes(&self) -> Self::Array {
43        self.0.to_bytes()
44    }
45
46    #[inline]
47    fn from_bytes(bytes: &[u8]) -> Result<Self> {
48        Ok(Self(u64::from_bytes(bytes)?))
49    }
50}
51
52impl From<Version> for u64 {
53    fn from(value: Version) -> u64 {
54        value.0
55    }
56}
57
58impl From<u64> for Version {
59    fn from(value: u64) -> Self {
60        Self(value)
61    }
62}
63
64impl TryFrom<&Path> for Version {
65    type Error = Error;
66    fn try_from(value: &Path) -> Result<Self, Self::Error> {
67        let mut buf = [0; SIZE_OF_U64];
68        fs::read(value)?.as_slice().read_exact(&mut buf)?;
69        Self::from_bytes(&buf)
70    }
71}
72
73impl Add<Version> for Version {
74    type Output = Self;
75    fn add(self, rhs: Version) -> Self::Output {
76        Self(self.0 + rhs.0)
77    }
78}
79
80impl Sum for Version {
81    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
82        iter.fold(Self::ZERO, Add::add)
83    }
84}