an efficient binary archive format

implement more options for opening files in rust

+34 -9
+34 -9
src/lib.rs
··· 78 78 } 79 79 80 80 impl Bindle { 81 + /// Create a new bindle file, this will overwrite the existing file 82 + pub fn create<P: AsRef<Path>>(path: P) -> io::Result<Self> { 83 + let path_buf = path.as_ref().to_path_buf(); 84 + let opts = OpenOptions::new() 85 + .truncate(true) 86 + .read(true) 87 + .write(true) 88 + .create(true) 89 + .to_owned(); 90 + Self::new(path_buf, opts) 91 + } 92 + 93 + /// Open or create a bindle file 81 94 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> { 82 95 let path_buf = path.as_ref().to_path_buf(); 83 - let mut file = OpenOptions::new() 96 + let opts = OpenOptions::new() 84 97 .read(true) 85 98 .write(true) 86 99 .create(true) 87 - .open(&path_buf)?; 100 + .to_owned(); 101 + Self::new(path_buf, opts) 102 + } 103 + 104 + /// Open a bindle file, this will not create it if it doesn't exist 105 + pub fn load<P: AsRef<Path>>(path: P) -> io::Result<Self> { 106 + let path_buf = path.as_ref().to_path_buf(); 107 + let opts = OpenOptions::new().read(true).write(true).to_owned(); 108 + Self::new(path_buf, opts) 109 + } 110 + 111 + /// Create a new `Bindle` from a path and file, the path must match the file 112 + pub fn new(path: PathBuf, opts: OpenOptions) -> io::Result<Self> { 113 + let mut file = opts.open(&path)?; 88 114 file.lock_shared()?; 89 - 90 115 let len = file.metadata()?.len(); 91 116 if len == 0 { 92 117 file.write_all(BNDL_MAGIC)?; 93 118 return Ok(Self { 94 - path: path_buf, 119 + path, 95 120 file, 96 121 mmap: None, 97 122 index: BTreeMap::new(), ··· 125 150 } 126 151 127 152 Ok(Self { 128 - path: path_buf, 153 + path, 129 154 file, 130 155 mmap: Some(m), 131 156 index, ··· 193 218 pub fn vacuum(&mut self) -> io::Result<()> { 194 219 let tmp_path = self.path.with_extension("tmp"); 195 220 196 - // 1. Create and populate the temporary file 221 + // Create and populate the temporary file 197 222 { 198 223 let mut new_file = OpenOptions::new() 199 224 .write(true) ··· 241 266 // new_file is closed here when it goes out of scope 242 267 } 243 268 244 - // 2. CRITICAL: Release ALL handles to the original file 269 + // Release ALL handles to the original file 245 270 drop(self.mmap.take()); 246 271 let _ = self.file.unlock(); 247 272 ··· 249 274 let old_file = std::mem::replace(&mut self.file, File::open(&tmp_path)?); 250 275 drop(old_file); 251 276 252 - // 3. Perform the atomic rename while no handles point to the original path 277 + // Perform the atomic rename while no handles point to the original path 253 278 std::fs::rename(&tmp_path, &self.path)?; 254 279 255 - // 4. Re-establish the state for the Bindle struct 280 + // Re-establish the state for the Bindle struct 256 281 let file = OpenOptions::new().read(true).write(true).open(&self.path)?; 257 282 file.lock_shared()?; 258 283 let mmap = unsafe { Mmap::map(&file)? };