Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ Cargo.lock
/tests/temp/lib/*/*

.vscode/
.idea/

68 changes: 67 additions & 1 deletion src/file.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use error::{Error, ErrorKind, Result};
use std;
use std::cmp;
use std::fs::{remove_file, File};
use std::io::{Read, Write};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;

/// Options and flags which can be used to configure how a file will be copied or moved.
Expand Down Expand Up @@ -383,3 +384,68 @@ where

Ok(f.write_all(content.as_bytes())?)
}

/// Information block which should be changed
pub struct Block {
pub begin: u64,
pub len: u64,
pub data: Vec<u8>,
}
pub trait ExtraFile {
fn change_block(&mut self, block: &Block, buffer_size: u64);
fn change_blocks(&mut self, block: Vec<Block>, buffer_size: u64);
}

impl ExtraFile for File {
fn change_block(&mut self, block: &Block, buffer_size: u64) {
let file_len = self.metadata().unwrap().len();
if file_len < (block.begin + block.len) {
//TODO make as error
panic!("The selected block is out of bounds file size!");
}

let mut bytes_to_move = file_len - (block.begin + block.len);
let mut move_cursor = file_len;
let data_len = block.data.len() as u64;
let is_move_left = block.len > data_len;
if is_move_left {
move_cursor = block.begin;
}
if block.len == data_len {
bytes_to_move = 0;
}
while bytes_to_move != 0 {
let bytes_this_time: u64 = cmp::min(buffer_size, bytes_to_move);
let mut r_buffer = vec![0; bytes_this_time as usize];
let rd_off: u64;
let wr_off: u64;
if is_move_left {
rd_off = move_cursor + block.len;
wr_off = rd_off - block.len + data_len;
move_cursor += bytes_this_time;
} else {
rd_off = move_cursor - bytes_this_time;
wr_off = rd_off - block.len + data_len;
move_cursor -= bytes_this_time;
}
self.seek(SeekFrom::Start(rd_off)).unwrap();
self.read(&mut r_buffer[..]).unwrap();
self.seek(SeekFrom::Start(wr_off)).unwrap();
self.write_all(&r_buffer).unwrap();
bytes_to_move -= bytes_this_time;
}
self.seek(SeekFrom::Start(block.begin)).unwrap();
self.write_all(&block.data).unwrap();
self.flush().unwrap();
if is_move_left {
self.set_len(file_len - (block.len - data_len)).unwrap();
}
}
fn change_blocks(&mut self, blocks: Vec<Block>, buffer_size: u64) {
let mut blocks = blocks;
blocks.sort_by(|a, b| b.begin.cmp(&a.begin));
for b in blocks {
self.change_block(&b, buffer_size.clone());
}
}
}
Loading