use super::{DatabaseId, VersionError, VersionResult};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DatabaseRestore {
source: DatabaseId,
target: DatabaseId,
}
impl DatabaseRestore {
pub fn new(source: DatabaseId) -> VersionResult<Self> {
let mut target = [0; 16];
getrandom::fill(&mut target).map_err(|error| {
crate::StorageBackendError::Other(format!(
"allocate database restore identity: {error}"
))
})?;
Self::from_identities(source, DatabaseId::from_bytes(target))
}
pub fn from_identities(source: DatabaseId, target: DatabaseId) -> VersionResult<Self> {
if source == target {
return Err(VersionError::InvalidRestoreIdentity);
}
Ok(Self { source, target })
}
pub const fn source(self) -> DatabaseId {
self.source
}
pub const fn target(self) -> DatabaseId {
self.target
}
pub fn needs_restore(self, current: DatabaseId) -> VersionResult<bool> {
if current == self.source {
Ok(true)
} else if current == self.target {
Ok(false)
} else {
Err(VersionError::WrongDatabase)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn restored_history_requests_distinguish_source_completion_and_foreign_databases() {
let source = DatabaseId::from_bytes([1; 16]);
let target = DatabaseId::from_bytes([2; 16]);
let request = DatabaseRestore::from_identities(source, target).unwrap();
assert!(request.needs_restore(source).unwrap());
assert!(!request.needs_restore(target).unwrap());
assert!(matches!(
request.needs_restore(DatabaseId::from_bytes([3; 16])),
Err(VersionError::WrongDatabase)
));
assert!(matches!(
DatabaseRestore::from_identities(source, source),
Err(VersionError::InvalidRestoreIdentity)
));
let generated = DatabaseRestore::new(source).unwrap();
assert_eq!(generated.source(), source);
assert_ne!(generated.target(), source);
assert_eq!(
DatabaseRestore::from_identities(generated.source(), generated.target()).unwrap(),
generated
);
}
}