use once_cell::sync::Lazy;
use std::cell::RefCell;
use std::fs::{File, OpenOptions};
use std::io::{BufReader, BufWriter, Read, Result, Write};
use std::path::Path;
use std::rc::Rc;
use std::sync::{Mutex, MutexGuard};
static SEQUENTIAL: Lazy<Mutex<()>> = Lazy::new(Mutex::default);
pub fn sequential<'a>() -> MutexGuard<'a, ()> {
SEQUENTIAL.lock().unwrap_or_else(|e| e.into_inner())
}
pub fn get_rc_ref_cell_empty_vec<T>() -> Rc<RefCell<std::vec::Vec<T>>> {
Rc::new(RefCell::new(vec![]))
}
pub fn get_read_only_file(path: &str) -> Result<File> {
OpenOptions::new().read(true).open(path)
}
pub fn get_reader_for_file(path: &str) -> Result<BufReader<File>> {
let file: File = get_read_only_file(path)?;
Ok(BufReader::new(file))
}
pub fn get_file_contents(path: &str) -> Result<Vec<u8>> {
let mut buf = Vec::new();
get_reader_for_file(path)?.read_to_end(&mut buf)?;
Ok(buf.to_owned())
}
pub fn get_read_and_write_file(path: &str) -> Result<File> {
remove_file(path)?;
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(false)
.read(true)
.open(path)?;
Ok(file)
}
pub fn get_writer_for_file(path: &str) -> Result<BufWriter<File>> {
let file: File = get_read_and_write_file(path)?;
Ok(BufWriter::new(file))
}
pub fn write_file_contents(path: &str, contents: &[u8]) -> Result<()> {
let file: File = get_read_and_write_file(path)?;
BufWriter::new(file).write_all(contents)
}
pub fn create_dir_all(path_dir: &str) -> Result<()> {
if !Path::new(path_dir).is_dir() {
std::fs::create_dir_all(path_dir)?;
}
Ok(())
}
pub fn remove_file(file_path: &str) -> Result<()> {
if Path::new(file_path).is_file() {
std::fs::remove_file(file_path)?
}
Ok(())
}
#[cfg(test)]
mod tests {
use std::io::Seek;
use super::*;
#[test]
fn test_sequential_no_error() {
let _lock = sequential();
}
#[test]
fn test_get_rc_ref_cell_empty_vec() {
let _lock = sequential();
let vec = get_rc_ref_cell_empty_vec::<u8>();
assert_eq!(vec.borrow().len(), 0);
}
#[test]
fn test_get_read_only_file() {
let _lock = sequential();
let mut file = get_read_only_file("./fixtures/test.txt").unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "some file content\n");
}
#[test]
fn test_get_reader_for_file() {
let _lock = sequential();
let mut reader = get_reader_for_file("./fixtures/test.txt").unwrap();
let mut contents = String::new();
reader.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "some file content\n");
}
#[test]
fn test_get_file_contents() {
let _lock = sequential();
let contents = get_file_contents("./fixtures/test.txt").unwrap();
assert_eq!(contents, b"some file content\n");
}
#[test]
fn test_get_read_and_write_file() {
let _lock = sequential();
let mut file = get_read_and_write_file("./test.txt").unwrap();
file.write_all(b"test\n").unwrap();
file.flush().unwrap();
let mut contents = String::new();
file.seek(std::io::SeekFrom::Start(0)).unwrap();
file.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "test\n");
}
#[test]
fn test_get_writer_for_file() {
let _lock = sequential();
let mut writer = get_writer_for_file("./test.txt").unwrap();
writer.write_all(b"test\n").unwrap();
writer.flush().unwrap();
let mut file = get_read_only_file("./test.txt").unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "test\n");
}
#[test]
fn test_write_file_contents() {
let _lock = sequential();
write_file_contents("./test.txt", b"test\n").unwrap();
let mut file = get_read_only_file("./test.txt").unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "test\n");
}
}