use std::{fs, mem};
use std::path::Path;
use std::slice::from_raw_parts_mut;
use std::io::{Error, Read, Result};
pub(crate) fn read_struct<R: ?Sized + Read, T: Sized>(reader: &mut R) -> Result<T> {
let mut obj: T = unsafe { mem::zeroed() };
let size = mem::size_of::<T>();
let buffer_slice = unsafe { from_raw_parts_mut(&mut obj as *mut _ as *mut u8, size) };
reader.read_exact(buffer_slice)?;
Ok(obj)
}
pub(crate) fn create_dir_all<P: AsRef<Path>>(path: P) -> Result<()> {
if path.as_ref().exists() {
if path.as_ref().is_dir() {
return Ok(());
} else if path.as_ref().is_file() {
fs::remove_file(&path)?;
}
}
Ok(fs::create_dir_all(&path)?)
}
pub(crate) fn create_parent_dir_all<D: AsRef<Path>>(destination: &D) -> Result<()> {
let parent = destination
.as_ref()
.parent()
.ok_or(Error::other(format!("Missing parent directory for {}", destination.as_ref().display())))?;
create_dir_all(parent)
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use fs::File;
use tempfile::tempdir;
use super::*;
#[derive(Debug, PartialEq)]
#[repr(C, packed)]
struct ReadStruct {
pub a: u32,
pub b: u16,
pub c: u32,
}
#[test]
fn read_struct_has_correct_fields() -> Result<()> {
let mut stream = Cursor::new(b"\x01\x00\x00\x00\x02\x00\x03\x00\x00\x00\x10\x11");
let result = read_struct::<Cursor<_>, ReadStruct>(&mut stream)?;
let expected = ReadStruct { a: 1, b: 2, c: 3 };
assert_eq!(result, expected);
Ok(())
}
#[test]
fn test_create_dir_all_new() {
let temp_dir = tempdir().unwrap();
let new_dir_path = temp_dir.path().join("test_create_dir_all_new");
assert!(!new_dir_path.exists());
create_dir_all(&new_dir_path).unwrap();
assert!(new_dir_path.exists());
assert!(new_dir_path.is_dir());
}
#[test]
fn test_create_dir_all_existing_dir() {
let temp_dir = tempdir().unwrap();
let existing_dir_path = temp_dir.path().join("existing_dir");
fs::create_dir(&existing_dir_path).unwrap();
assert!(existing_dir_path.exists());
assert!(existing_dir_path.is_dir());
create_dir_all(&existing_dir_path).unwrap();
assert!(existing_dir_path.exists());
assert!(existing_dir_path.is_dir());
}
#[test]
fn test_create_dir_all_replace_file() {
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("file");
File::create(&file_path).unwrap();
assert!(file_path.exists());
assert!(file_path.is_file());
create_dir_all(&file_path).unwrap();
assert!(file_path.exists());
assert!(file_path.is_dir());
}
}