#[cfg(test)]
mod tests;
use std::fmt;
use thiserror::Error;
use crate::svec::SecureVec;
#[derive(Debug, Error)]
pub enum MigrationError {
#[error("failed to migrate the revision 0 header into revision 1")]
Rev0(String),
}
pub trait Migration {
fn migrate_rev0(&self, userdata: &[u8]) -> Result<(u32, Vec<u8>), String>;
}
#[derive(Default)]
pub struct Migrator<'a>(Option<Box<dyn Migration + 'a>>);
impl<'a> Migrator<'a> {
pub fn with_migration<M: 'a + Migration>(mut self, migration: M) -> Self {
self.0 = Some(Box::new(migration));
self
}
pub fn migrate_rev0(
&self,
userdata: &[u8],
) -> Result<Option<(u32, SecureVec)>, MigrationError> {
if let Some(migration) = self.0.as_ref() {
match migration.migrate_rev0(userdata) {
Ok((sid, top_id)) => Ok(Some((sid, top_id.into()))),
Err(err) => Err(MigrationError::Rev0(err)),
}
} else {
Ok(None)
}
}
}
impl<'a> fmt::Debug for Migrator<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_tuple("Migrator")
.field(&self.0.as_ref().map(|_| "..."))
.finish()
}
}