use std::io;
use crate::entry::SessionEntry;
use crate::meta::SessionMeta;
pub trait SessionMigrator: Send + Sync {
fn source_version(&self) -> u32;
fn target_version(&self) -> u32;
fn migrate(
&self,
meta: &SessionMeta,
entries: Vec<SessionEntry>,
) -> io::Result<Vec<SessionEntry>>;
}
pub const CURRENT_VERSION: u32 = 1;
pub fn run_migrations(
meta: &mut SessionMeta,
entries: &mut Vec<SessionEntry>,
migrators: &[Box<dyn SessionMigrator>],
) -> io::Result<()> {
if meta.version > CURRENT_VERSION {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"unsupported session version {} (current: {CURRENT_VERSION})",
meta.version
),
));
}
while meta.version < CURRENT_VERSION {
let migrator = migrators
.iter()
.find(|m| m.source_version() == meta.version)
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
format!(
"no migrator found for version {} -> {}",
meta.version,
meta.version + 1
),
)
})?;
*entries = migrator.migrate(meta, std::mem::take(entries))?;
meta.version = migrator.target_version();
}
Ok(())
}
#[cfg(test)]
#[path = "migrate_tests.rs"]
mod tests;