tycho_storage/kv/
models.rs1use std::marker::PhantomData;
2
3use weedb::{ColumnFamily, MigrationError, Semver, VersionProvider, WeeDbRaw};
4
5use super::NamedTables;
6
7#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
8#[repr(transparent)]
9pub struct InstanceId(pub [u8; 16]);
10
11impl InstanceId {
12 #[inline]
13 pub fn from_slice(slice: &[u8]) -> Self {
14 Self(slice.try_into().expect("slice with incorrect length"))
15 }
16}
17
18impl rand::distr::Distribution<InstanceId> for rand::distr::StandardUniform {
19 #[inline]
20 fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> InstanceId {
21 InstanceId(rng.random())
22 }
23}
24
25impl AsRef<[u8]> for InstanceId {
26 #[inline(always)]
27 fn as_ref(&self) -> &[u8] {
28 self.0.as_ref()
29 }
30}
31
32pub struct StateVersionProvider<C> {
33 db_name: &'static str,
34 cf: PhantomData<C>,
35}
36
37impl<C> StateVersionProvider<C> {
38 pub const DB_NAME_KEY: &'static [u8] = b"__db_name";
39 pub const DB_VERSION_KEY: &'static [u8] = b"__db_version";
40
41 pub fn new<T: NamedTables>() -> Self
42 where
43 C: ColumnFamily,
44 {
45 Self {
46 db_name: T::NAME,
47 cf: PhantomData,
48 }
49 }
50}
51
52impl<C: ColumnFamily> VersionProvider for StateVersionProvider<C> {
53 fn get_version(&self, db: &WeeDbRaw) -> Result<Option<Semver>, MigrationError> {
54 let state = db.instantiate_table::<C>();
55
56 if let Some(db_name) = state.get(Self::DB_NAME_KEY)?
57 && db_name.as_ref() != self.db_name.as_bytes()
58 {
59 return Err(MigrationError::Custom(
60 format!(
61 "expected db name: {}, got: {}",
62 self.db_name,
63 String::from_utf8_lossy(db_name.as_ref())
64 )
65 .into(),
66 ));
67 }
68
69 let value = state.get(Self::DB_VERSION_KEY)?;
70 match value {
71 Some(version) => {
72 let slice = version.as_ref();
73 slice
74 .try_into()
75 .map_err(|_e| MigrationError::InvalidDbVersion)
76 .map(Some)
77 }
78 None => Ok(None),
79 }
80 }
81
82 fn set_version(&self, db: &WeeDbRaw, version: Semver) -> Result<(), MigrationError> {
83 let state = db.instantiate_table::<C>();
84 state.insert(Self::DB_NAME_KEY, self.db_name.as_bytes())?;
85 state.insert(Self::DB_VERSION_KEY, version)?;
86 Ok(())
87 }
88}