Skip to content

Instantly share code, notes, and snippets.

@adetaylor
Last active November 22, 2022 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adetaylor/5cf9e117f34a9cbb49d8fab4368a27f7 to your computer and use it in GitHub Desktop.
Save adetaylor/5cf9e117f34a9cbb49d8fab4368a27f7 to your computer and use it in GitHub Desktop.
#[derive(Clone)]
struct CloneableFile {
file: Arc<Mutex<File>>,
pos: u64,
// TODO determine and store this once instead of per cloneable file
file_length: Option<u64>,
}
impl CloneableFile {
fn new(file: File) -> Self {
Self {
file: Arc::new(Mutex::new(file)),
pos: 0u64,
file_length: None,
}
}
}
impl CloneableFile {
fn ascertain_file_length(&mut self) -> u64 {
match self.file_length {
Some(file_length) => file_length,
None => {
let len = self.file.lock().unwrap().metadata().unwrap().len();
self.file_length = Some(len);
len
}
}
}
}
impl Read for CloneableFile {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let mut underlying_file = self.file.lock().expect("Unable to get underlying file");
// TODO share an object which knows current position to avoid unnecessary
// seeks
underlying_file.seek(SeekFrom::Start(self.pos))?;
let read_result = underlying_file.read(buf);
if let Ok(bytes_read) = read_result {
// TODO, once stabilised, use checked_add_signed
self.pos += bytes_read as u64;
}
read_result
}
}
impl Seek for CloneableFile {
fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
let new_pos = match pos {
SeekFrom::Start(pos) => pos,
SeekFrom::End(offset_from_end) => {
let file_len = self.ascertain_file_length();
// TODO, once stabilised, use checked_add_signed
file_len - (-offset_from_end as u64)
}
// TODO, once stabilised, use checked_add_signed
SeekFrom::Current(offset_from_pos) => {
if offset_from_pos == 0 {
self.pos
} else if offset_from_pos > 0 {
self.pos + (offset_from_pos as u64)
} else {
self.pos - ((-offset_from_pos) as u64)
}
}
};
self.pos = new_pos;
Ok(new_pos)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment