use crate::error::{Result, StoreError};
pub const STORE_FORMAT_VERSION: u32 = 1;
pub const MIN_READABLE_VERSION: u32 = 1;
pub const MIN_WRITABLE_VERSION: u32 = STORE_FORMAT_VERSION;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Compatibility {
Current,
UpgradeRecommended,
UnsupportedTooOld,
UnsupportedTooNew,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MigrationPlan {
pub from: u32,
pub to: u32,
pub automatic: bool,
pub message: String,
}
#[must_use]
pub const fn compatibility(version: u32) -> Compatibility {
if version == STORE_FORMAT_VERSION {
Compatibility::Current
} else if version >= MIN_READABLE_VERSION && version < STORE_FORMAT_VERSION {
Compatibility::UpgradeRecommended
} else if version < MIN_READABLE_VERSION {
Compatibility::UnsupportedTooOld
} else {
Compatibility::UnsupportedTooNew
}
}
pub fn ensure_readable(version: u32) -> Result<()> {
match compatibility(version) {
Compatibility::Current | Compatibility::UpgradeRecommended => Ok(()),
Compatibility::UnsupportedTooOld | Compatibility::UnsupportedTooNew => {
Err(StoreError::UnsupportedVersion { version }.into())
}
}
}
pub fn ensure_writable(version: u32) -> Result<()> {
if version < MIN_WRITABLE_VERSION || version > STORE_FORMAT_VERSION {
return Err(StoreError::UnsupportedVersion { version }.into());
}
Ok(())
}
#[must_use]
pub fn plan(from: u32) -> Option<MigrationPlan> {
match compatibility(from) {
Compatibility::Current => None,
Compatibility::UpgradeRecommended => Some(MigrationPlan {
from,
to: STORE_FORMAT_VERSION,
automatic: true,
message: format!(
"upgrade store format from version {} to {}",
from, STORE_FORMAT_VERSION
),
}),
Compatibility::UnsupportedTooOld => Some(MigrationPlan {
from,
to: STORE_FORMAT_VERSION,
automatic: false,
message: format!("store version {} is too old for automatic migration", from),
}),
Compatibility::UnsupportedTooNew => Some(MigrationPlan {
from,
to: STORE_FORMAT_VERSION,
automatic: false,
message: format!("store version {} is newer than this binary supports", from),
}),
}
}
pub fn migrate_version(from: u32) -> Result<u32> {
match compatibility(from) {
Compatibility::Current => Ok(STORE_FORMAT_VERSION),
Compatibility::UpgradeRecommended => {
Ok(STORE_FORMAT_VERSION)
}
Compatibility::UnsupportedTooOld | Compatibility::UnsupportedTooNew => {
Err(StoreError::UnsupportedVersion { version: from }.into())
}
}
}
#[must_use]
pub fn describe_current() -> &'static str {
"version 1: JSON snapshot file with ordered key/value records"
}