clone_file/
common.rs

1use std::fs::{self, File};
2use std::io::{self, Read, Seek, SeekFrom};
3use std::path::Path;
4
5/// Tries to clone the file with [crate::clone_file], falling back to [fs::copy] on error
6///
7/// Returns `Ok(None)` on successful clone, `Ok(Some(copied_byte_count))` on successful [fs::copy].
8pub fn clone_or_copy_file<P: AsRef<Path>, Q: AsRef<Path>>(
9    src: P,
10    dest: Q,
11) -> io::Result<Option<u64>> {
12    if let Ok(_) = crate::clone_file(&src, &dest) {
13        Ok(None)
14    } else {
15        fs::copy(&src, &dest).and_then(|x| Ok(Some(x)))
16    }
17}
18
19/// Tries to clone a range of bytes to another file, falling back to [copy_file_range] on error
20///
21/// Returns `Ok(None)` on successful clone, `Ok(Some(copied_byte_count))` on successful naive copy.
22pub fn clone_or_copy_file_range<P: AsRef<Path>, Q: AsRef<Path>>(
23    src: P,
24    src_offset: u64,
25    src_length: u64,
26    dest: Q,
27    dest_offset: u64,
28) -> io::Result<Option<u64>> {
29    if let Ok(_) = crate::clone_file_range(&src, src_offset, src_length, &dest, dest_offset) {
30        Ok(None)
31    } else {
32        todo!()
33    }
34}
35
36/// Naively copy a range of bytes from one file to another
37///
38/// This function is mainly implemented as a fallback for [clone_or_copy_file_range].
39///
40/// Returns `Ok(copied_byte_count)` on success.
41pub fn copy_file_range<P: AsRef<Path>, Q: AsRef<Path>>(
42    src: P,
43    src_offset: u64,
44    src_length: u64,
45    dest: Q,
46    dest_offset: u64,
47) -> io::Result<u64> {
48    let mut src_file = File::open(src)?;
49    let mut dest_file = File::options().write(true).create(true).open(dest)?;
50
51    src_file.seek(SeekFrom::Start(src_offset))?;
52    let mut src_file = src_file.take(src_length);
53
54    dest_file.seek(SeekFrom::Start(dest_offset))?;
55
56    io::copy(&mut src_file, &mut dest_file)
57}