Skip to content

Commit 11b8d3a

Browse files
committed
add open_rw method
1 parent 45e71b5 commit 11b8d3a

File tree

1 file changed

+40
-8
lines changed

1 file changed

+40
-8
lines changed

src/lib.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#[macro_use]
1111
extern crate amplify;
1212

13-
use std::fs::File;
13+
use std::fs::{File, OpenOptions};
1414
use std::io::{self, Read, Write};
1515
use std::ops::{Deref, DerefMut};
1616
use std::path::Path;
@@ -97,26 +97,43 @@ impl<const MAGIC: u64, const VERSION: u16> BinFile<MAGIC, VERSION> {
9797
/// bytes) and version number (2 bytes). The produced file stream will start at byte offset 10.
9898
pub fn open(path: impl AsRef<Path>) -> io::Result<Self> {
9999
let path = path.as_ref();
100-
let mut file = File::open(&path)?;
100+
let mut file = Self(File::open(&path)?);
101+
file.check(&path)?;
102+
Ok(file)
103+
}
104+
105+
/// Attempts to open a file in read-write mode the same way as [`OpenOptions::new`], followed by
106+
/// `read(true)` and `write(true)` calls does.
107+
///
108+
/// Then it reads first 10 bytes of the file and verifies them to match the magic number (8
109+
/// bytes) and version number (2 bytes). The produced file stream will start at byte offset 10.
110+
pub fn open_rw(path: impl AsRef<Path>) -> io::Result<Self> {
111+
let path = path.as_ref();
112+
let mut file = Self(OpenOptions::new().read(true).write(true).open(&path)?);
113+
file.check(&path)?;
114+
Ok(file)
115+
}
116+
117+
fn check(&mut self, filename: &Path) -> io::Result<()> {
101118
let mut magic = [0u8; 8];
102-
file.read_exact(&mut magic)?;
119+
self.read_exact(&mut magic)?;
103120
if magic != MAGIC.to_be_bytes() {
104121
return Err(io::Error::other(BinFileError::InvalidMagic {
105-
filename: path.to_string_lossy().to_string(),
122+
filename: filename.to_string_lossy().to_string(),
106123
expected: MAGIC,
107124
actual: u64::from_be_bytes(magic),
108125
}));
109126
}
110127
let mut version = [0u8; 2];
111-
file.read_exact(&mut version)?;
128+
self.read_exact(&mut version)?;
112129
if version != VERSION.to_be_bytes() {
113130
return Err(io::Error::other(BinFileError::InvalidVersion {
114-
filename: path.to_string_lossy().to_string(),
131+
filename: filename.to_string_lossy().to_string(),
115132
expected: VERSION,
116133
actual: u16::from_be_bytes(version),
117134
}));
118135
}
119-
Ok(Self(file))
136+
Ok(())
120137
}
121138
}
122139

@@ -177,7 +194,7 @@ mod tests {
177194
}
178195

179196
#[test]
180-
fn open() {
197+
fn open_ro() {
181198
const MY_MAGIC: u64 = u64::from_be_bytes(*b"MYMAGIC!");
182199
let mut file = BinFile::<MY_MAGIC, 1>::create("target/test3").unwrap();
183200
file.write_all(b"hello world").unwrap();
@@ -190,6 +207,21 @@ mod tests {
190207
assert_eq!(buf, b"hello world");
191208
}
192209

210+
#[test]
211+
fn open_rw() {
212+
const MY_MAGIC: u64 = u64::from_be_bytes(*b"MYMAGIC!");
213+
let mut file = BinFile::<MY_MAGIC, 1>::create("target/test5").unwrap();
214+
file.write_all(b"hello world").unwrap();
215+
file.flush().unwrap();
216+
217+
let mut file = BinFile::<MY_MAGIC, 1>::open_rw("target/test5").unwrap();
218+
let mut buf = Vec::new();
219+
let check = file.read_to_end(&mut buf).unwrap();
220+
assert_eq!(check, 11);
221+
assert_eq!(buf, b"hello world");
222+
file.write_all(b"\nand hello again").unwrap();
223+
}
224+
193225
#[test]
194226
fn open_wrong_magic() {
195227
const MY_MAGIC: u64 = u64::from_be_bytes(*b"MYMAGIC!");

0 commit comments

Comments
 (0)