···7878}
79798080impl Bindle {
8181+ /// Create a new bindle file, this will overwrite the existing file
8282+ pub fn create<P: AsRef<Path>>(path: P) -> io::Result<Self> {
8383+ let path_buf = path.as_ref().to_path_buf();
8484+ let opts = OpenOptions::new()
8585+ .truncate(true)
8686+ .read(true)
8787+ .write(true)
8888+ .create(true)
8989+ .to_owned();
9090+ Self::new(path_buf, opts)
9191+ }
9292+9393+ /// Open or create a bindle file
8194 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
8295 let path_buf = path.as_ref().to_path_buf();
8383- let mut file = OpenOptions::new()
9696+ let opts = OpenOptions::new()
8497 .read(true)
8598 .write(true)
8699 .create(true)
8787- .open(&path_buf)?;
100100+ .to_owned();
101101+ Self::new(path_buf, opts)
102102+ }
103103+104104+ /// Open a bindle file, this will not create it if it doesn't exist
105105+ pub fn load<P: AsRef<Path>>(path: P) -> io::Result<Self> {
106106+ let path_buf = path.as_ref().to_path_buf();
107107+ let opts = OpenOptions::new().read(true).write(true).to_owned();
108108+ Self::new(path_buf, opts)
109109+ }
110110+111111+ /// Create a new `Bindle` from a path and file, the path must match the file
112112+ pub fn new(path: PathBuf, opts: OpenOptions) -> io::Result<Self> {
113113+ let mut file = opts.open(&path)?;
88114 file.lock_shared()?;
8989-90115 let len = file.metadata()?.len();
91116 if len == 0 {
92117 file.write_all(BNDL_MAGIC)?;
93118 return Ok(Self {
9494- path: path_buf,
119119+ path,
95120 file,
96121 mmap: None,
97122 index: BTreeMap::new(),
···125150 }
126151127152 Ok(Self {
128128- path: path_buf,
153153+ path,
129154 file,
130155 mmap: Some(m),
131156 index,
···193218 pub fn vacuum(&mut self) -> io::Result<()> {
194219 let tmp_path = self.path.with_extension("tmp");
195220196196- // 1. Create and populate the temporary file
221221+ // Create and populate the temporary file
197222 {
198223 let mut new_file = OpenOptions::new()
199224 .write(true)
···241266 // new_file is closed here when it goes out of scope
242267 }
243268244244- // 2. CRITICAL: Release ALL handles to the original file
269269+ // Release ALL handles to the original file
245270 drop(self.mmap.take());
246271 let _ = self.file.unlock();
247272···249274 let old_file = std::mem::replace(&mut self.file, File::open(&tmp_path)?);
250275 drop(old_file);
251276252252- // 3. Perform the atomic rename while no handles point to the original path
277277+ // Perform the atomic rename while no handles point to the original path
253278 std::fs::rename(&tmp_path, &self.path)?;
254279255255- // 4. Re-establish the state for the Bindle struct
280280+ // Re-establish the state for the Bindle struct
256281 let file = OpenOptions::new().read(true).write(true).open(&self.path)?;
257282 file.lock_shared()?;
258283 let mmap = unsafe { Mmap::map(&file)? };