versioned-file
This readme is copy-pasted from the rust docs, and may be out of date.
The VersionedFile crate provides a wrapper to async_std::File which adds an invisible 4096 byte
header to the file which tracks things like the file version number and the file identifier.
When using methods like seek
and set_len
, the header will be ignored. For example, calling
set_len(0) will result in a file that has a logical size of 0 but the 4096 byte file header
will still be intact.
The most useful portion of the header is the version number, which allows the software to
easily detect when a file is using an out-of-date version and complete an update on that file.
The other part of the header is an identifier which may help to recover the file in the event
that the file's name is changed or lost unexpectedly.
When a VersionedFile is opened, the caller passes in the latest version of the file, along with
a chain of upgrades that can be used to upgrade older versions of the file to the most recent
version. Finally, the identifier is also supplied so that an error can be thrown if the file
has the wrong identifier.
use async_std::io::SeekFrom;
use std::path::PathBuf;
use anyhow::{bail, Result, Error};
use versioned_file::{open_file, wrap_upgrade_process, Upgrade, VersionedFile};
#[async_std::main]
async fn main() {
let path = PathBuf::from("target/docs-example-file.txt");
let identifier = "VersionedFileDocs::example.txt";
let mut versioned_file = open_file(&path, identifier, 1, &Vec::new()).await.unwrap();
versioned_file.write_all(b"hello, world!").await.unwrap();
versioned_file.seek(SeekFrom::Start(0)).await.unwrap();
let mut buf = vec![0u8; versioned_file.len().await.unwrap() as usize];
versioned_file.read_exact(&mut buf).await.unwrap();
if buf != b"hello, world!" {
panic!("example did not read correctly");
}
}
use async_std::io::SeekFrom;
use std::path::PathBuf;
use anyhow::{bail, Result, Error};
use versioned_file::{open_file, wrap_upgrade_process, Upgrade, VersionedFile};
async fn example_upgrade(
mut vf: VersionedFile,
initial_version: u8,
updated_version: u8,
) -> Result<(), Error> {
if initial_version != 1 || updated_version != 2 {
bail!("wrong version");
}
vf.set_len(0).await.unwrap();
let new_data = b"hello, update!";
vf.write_all(new_data).await.unwrap();
Ok(())
}
#[async_std::main]
async fn main() {
let path = PathBuf::from("target/docs-example-file.txt");
let identifier = "VersionedFileDocs::example.txt";
let upgrade = Upgrade {
initial_version: 1,
updated_version: 2,
process: wrap_upgrade_process(example_upgrade),
};
let mut vf = open_file(&path, identifier, 2, &vec![upgrade]).await.unwrap();
let mut buf = vec![0u8; vf.len().await.unwrap() as usize];
vf.read_exact(&mut buf).await.unwrap();
if buf != b"hello, update!" {
panic!("example did not update correctly");
}
std::fs::remove_file(PathBuf::from("target/docs-example-file.txt"));
}