use tokio::fs::{File,OpenOptions,remove_file};
use std::path::Path;
use tokio::io::{AsyncWriteExt,AsyncReadExt,AsyncSeekExt};
use std::fs::Metadata;
use std::io::{SeekFrom};
const MB_1:u64 = 1_000_000;
pub async fn init_map(path:String,min_que_size:u64)->Result<(File,Metadata),&'static str>{
let build = Path::new(&path);
if !build.exists() || false{
let mut file_builder = OpenOptions::new();
file_builder.write(true)
.read(true)
.create(true);
let mut file:File;
match file_builder.open(build).await{
Ok(f)=>{
file = f;
},
Err(_)=>{
return Err("failed-create_file");
}
}
match expand(&mut file, &min_que_size).await{
Ok(_)=>{},
Err(_e)=>{
println!("!!! failed-expand-new_map : {:?}",_e);
return Err("failed-expand-new_map");
}
}
match file.metadata().await{
Ok(v)=>{
return Ok((file,v));
},
Err(_)=>{
return Err("failed-get-metadata");
}
}
}
let mut file:File;
match OpenOptions::new()
.write(true)
.read(true)
.open(build)
.await
{
Ok(f)=>{
file = f;
},
Err(_)=>{
return Err("failed-create_file");
}
}
let metadata:Metadata;
match file.metadata().await{
Ok(v)=>{
metadata = v;
},
Err(_)=>{
return Err("failed-get-metadata");
}
}
let file_size = metadata.len();
if file_size < min_que_size{
match expand(&mut file, &(min_que_size - file_size)).await{
Ok(_)=>{
},
Err(_e)=>{
return Err("failed-expand-existing_map");
}
}
}
match file.metadata().await{
Ok(metadata)=>{
return Ok((file,metadata));
},
Err(_)=>{
return Err("failed-get-metadata");
}
}
}
pub async fn expand(file:&mut File,size_og:&u64)->Result<(),&'static str>{
match file.seek(SeekFrom::End(0)).await{
Ok(_)=>{},
Err(_)=>{
return Err("failed-seek");
}
}
let mut size = size_og.clone();
let min_expansion_mb:u64;
if size > (MB_1 * 100){
min_expansion_mb = 100 * MB_1; } else if size > (MB_1 * 50){
min_expansion_mb = 50 * MB_1; } else if size > (MB_1 * 25){
min_expansion_mb = 25 * MB_1; } else if size > (MB_1 * 20){
min_expansion_mb = 20 * MB_1; } else if size > (MB_1 * 15){
min_expansion_mb = 15 * MB_1; } else if size > (MB_1 * 10){
min_expansion_mb = 10 * MB_1; } else if size > (MB_1 * 5){
min_expansion_mb = 5 * MB_1; } else {
min_expansion_mb = 0; }
if min_expansion_mb > 0{
let mut build = vec![];
for _ in 0..min_expansion_mb{
build.push(0);
}
loop{
if size < min_expansion_mb{break;}
match file.write_all(&build).await{
Ok(_v)=>{
size -= min_expansion_mb;
},
Err(_)=>{
return Err("failed-write_to_file");
}
}
}
}
let mut build = vec![];
for _ in 0..size.clone(){
build.push(0);
}
match file.write_all(&build).await{
Ok(_)=>{
return Ok(());
},
Err(_)=>{
return Err("failed-write_to_file");
}
}
}
pub async fn remove_chunk(file:&mut File,start_at:usize,len:usize)->Result<(),&'static str>{
match file.seek(SeekFrom::Start(start_at as u64)).await{
Ok(_)=>{},
Err(_e)=>{
return Err("failed-seek");
}
}
let mut collect:Vec<u8> = Vec::with_capacity(len as usize);
for _ in 0..len{
collect.push(0);
}
match file.write(&collect).await{
Ok(_)=>{
return Ok(());
},
Err(_)=>{
return Err("failed-build_frame-create_file");
}
}
}
pub async fn write_chunk(file:&mut File,start_at:u64,buffer:Vec<u8>)->Result<(),&'static str>{
match file.seek(SeekFrom::Start(start_at)).await{
Ok(_)=>{},
Err(_e)=>{
return Err("failed-seek");
}
}
match file.write(&buffer).await{
Ok(_)=>{
return Ok(());
},
Err(_)=>{
return Err("failed-read_chunk");
}
}
}
pub async fn read_chunk(file:&mut File,buffer:&mut Vec<u8>,start_at:u64,read_len:u64)->Result<usize,&'static str>{
match file.seek(SeekFrom::Start(start_at)).await{
Ok(_)=>{},
Err(_e)=>{
return Err("failed-seek");
}
}
match file.take(read_len).read_to_end(buffer).await{
Ok(v)=>{
return Ok(v);
},
Err(_)=>{
return Err("failed-read_chunk");
}
}
}
#[allow(dead_code)]
pub async fn read_full(path:String){
let mut file_builder = OpenOptions::new();
file_builder
.write(true)
.read(true)
.create(true);
let mut file:File;
match file_builder.open(path).await{
Ok(f)=>{
file = f;
},
Err(_)=>{
return;
}
}
let mut buffer = Vec::new();
match file.seek(SeekFrom::Start(0)).await{
Ok(_)=>{},
Err(_)=>{
return;
}
}
match file.read_to_end(&mut buffer).await{
Ok(_)=>{},
Err(_)=>{
return;
}
}
}
#[allow(dead_code)]
pub async fn delete_file(path:&String){
match remove_file(path).await{
Ok(_)=>{},
Err(_e)=>{
}
}
}
#[allow(dead_code)]
pub async fn write_new_file(path:&String,buffer:Vec<u8>)->Result<(),&'static str>{
let mut file:File;
match File::create(path).await{
Ok(f)=>{file = f;},
Err(_)=>{return Err("failed-open_file");}
}
match file.write(&buffer).await{
Ok(_)=>{
return Ok(());
},
Err(_)=>{
return Err("failed-read_chunk");
}
}
}