Last active
November 22, 2022 16:00
-
-
Save adetaylor/5cf9e117f34a9cbb49d8fab4368a27f7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[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