use core::str;
use std::borrow::Cow;
use std::env::VarError;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::io;
use std::io::Error;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;
use std::time::SystemTime;
pub mod boxed;
pub mod impls;
pub trait EnvCurrentDir {
fn env_current_dir(&self) -> io::Result<PathBuf>;
}
pub trait BaseEnvSetCurrentDir {
#[doc(hidden)]
fn base_env_set_current_dir(&self, path: &Path) -> io::Result<()>;
}
pub trait EnvSetCurrentDir: BaseEnvSetCurrentDir {
#[inline]
fn env_set_current_dir(&self, path: impl AsRef<Path>) -> io::Result<()> {
self.base_env_set_current_dir(path.as_ref())
}
}
impl<T: BaseEnvSetCurrentDir> EnvSetCurrentDir for T {}
pub trait BaseEnvVar {
#[doc(hidden)]
fn base_env_var_os(&self, key: &OsStr) -> Option<OsString>;
}
pub trait EnvVar: BaseEnvVar {
#[inline]
fn env_var_os(&self, key: impl AsRef<OsStr>) -> Option<OsString> {
self.base_env_var_os(key.as_ref())
}
fn env_var(&self, key: impl AsRef<OsStr>) -> Result<String, VarError> {
match self.env_var_os(key) {
Some(val) => val.into_string().map_err(VarError::NotUnicode),
None => Err(VarError::NotPresent),
}
}
fn env_var_path(&self, key: impl AsRef<OsStr>) -> Option<PathBuf> {
self
.env_var_os(key)
.and_then(|h| if h.is_empty() { None } else { Some(h) })
.map(|value| {
#[cfg(all(target_arch = "wasm32", feature = "wasm"))]
{
impls::wasm_string_to_path(value.to_string_lossy().to_string())
}
#[cfg(any(not(target_arch = "wasm32"), not(feature = "wasm")))]
{
PathBuf::from(value)
}
})
}
}
impl<T: BaseEnvVar> EnvVar for T {}
pub trait BaseEnvSetVar {
#[doc(hidden)]
fn base_env_set_var(&self, key: &OsStr, value: &OsStr);
}
pub trait EnvSetVar: BaseEnvSetVar {
fn env_set_var(&self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) {
self.base_env_set_var(key.as_ref(), value.as_ref())
}
}
impl<T: BaseEnvSetVar> EnvSetVar for T {}
pub trait EnvUmask {
fn env_umask(&self) -> io::Result<u32>;
}
pub trait EnvSetUmask {
fn env_set_umask(&self, umask: u32) -> io::Result<u32>;
}
pub trait EnvCacheDir {
fn env_cache_dir(&self) -> Option<PathBuf>;
}
pub trait EnvHomeDir {
fn env_home_dir(&self) -> Option<PathBuf>;
}
pub trait EnvTempDir {
fn env_temp_dir(&self) -> io::Result<PathBuf>;
}
#[cfg(windows)]
type CustomFlagsValue = u32;
#[cfg(not(windows))]
type CustomFlagsValue = i32;
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(default, rename_all = "camelCase"))]
#[non_exhaustive] pub struct OpenOptions {
pub read: bool,
pub write: bool,
pub create: bool,
pub truncate: bool,
pub append: bool,
pub create_new: bool,
pub mode: Option<u32>,
pub custom_flags: Option<CustomFlagsValue>,
pub access_mode: Option<u32>,
pub share_mode: Option<u32>,
pub attributes: Option<u32>,
pub security_qos_flags: Option<u32>,
}
impl OpenOptions {
pub fn new() -> Self {
Self::default()
}
pub fn new_read() -> Self {
Self {
read: true,
write: false,
create: false,
truncate: false,
append: false,
create_new: false,
..Default::default()
}
}
#[deprecated(note = "use `new_write` instead")]
pub fn write() -> Self {
Self::new_write()
}
pub fn new_write() -> Self {
Self {
read: false,
write: true,
create: true,
truncate: true,
append: false,
create_new: false,
..Default::default()
}
}
pub fn new_append() -> Self {
Self {
read: false,
write: true,
create: false,
truncate: false,
append: true,
create_new: false,
..Default::default()
}
}
#[inline]
pub fn read(&mut self) -> &mut Self {
self.read = true;
self
}
#[inline]
pub fn create(&mut self) -> &mut Self {
self.create = true;
self
}
#[inline]
pub fn truncate(&mut self) -> &mut Self {
self.truncate = true;
self
}
#[inline]
pub fn append(&mut self) -> &mut Self {
self.append = true;
self
}
#[inline]
pub fn create_new(&mut self) -> &mut Self {
self.create_new = true;
self
}
#[inline]
pub fn mode(&mut self, mode: u32) -> &mut Self {
self.mode = Some(mode);
self
}
#[inline]
pub fn custom_flags(&mut self, flags: CustomFlagsValue) -> &mut Self {
self.custom_flags = Some(flags);
self
}
#[inline]
pub fn access_mode(&mut self, value: u32) -> &mut Self {
self.access_mode = Some(value);
self
}
#[inline]
pub fn share_mode(&mut self, value: u32) -> &mut Self {
self.share_mode = Some(value);
self
}
#[inline]
pub fn attributes(&mut self, value: u32) -> &mut Self {
self.attributes = Some(value);
self
}
#[inline]
pub fn security_qos_flags(&mut self, value: u32) -> &mut Self {
self.security_qos_flags = Some(value);
self
}
}
pub trait BaseFsCanonicalize {
#[doc(hidden)]
fn base_fs_canonicalize(&self, path: &Path) -> io::Result<PathBuf>;
}
pub trait FsCanonicalize: BaseFsCanonicalize {
#[inline]
fn fs_canonicalize(&self, path: impl AsRef<Path>) -> io::Result<PathBuf> {
self.base_fs_canonicalize(path.as_ref())
}
}
impl<T: BaseFsCanonicalize> FsCanonicalize for T {}
pub trait BaseFsChown {
#[doc(hidden)]
fn base_fs_chown(
&self,
path: &Path,
uid: Option<u32>,
gid: Option<u32>,
) -> io::Result<()>;
}
pub trait FsChown: BaseFsChown {
#[inline]
fn fs_chown(
&self,
path: impl AsRef<Path>,
uid: Option<u32>,
gid: Option<u32>,
) -> io::Result<()> {
self.base_fs_chown(path.as_ref(), uid, gid)
}
}
impl<T: BaseFsChown> FsChown for T {}
pub trait BaseFsSymlinkChown {
#[doc(hidden)]
fn base_fs_symlink_chown(
&self,
path: &Path,
uid: Option<u32>,
gid: Option<u32>,
) -> io::Result<()>;
}
pub trait FsSymlinkChown: BaseFsSymlinkChown {
#[inline]
fn fs_symlink_chown(
&self,
path: impl AsRef<Path>,
uid: Option<u32>,
gid: Option<u32>,
) -> io::Result<()> {
self.base_fs_symlink_chown(path.as_ref(), uid, gid)
}
}
impl<T: BaseFsSymlinkChown> FsSymlinkChown for T {}
pub trait BaseFsCloneFile {
#[doc(hidden)]
fn base_fs_clone_file(&self, from: &Path, to: &Path) -> io::Result<()>;
}
pub trait FsCloneFile: BaseFsCloneFile {
#[inline]
fn fs_clone_file(
&self,
from: impl AsRef<Path>,
to: impl AsRef<Path>,
) -> io::Result<()> {
self.base_fs_clone_file(from.as_ref(), to.as_ref())
}
}
impl<T: BaseFsCloneFile> FsCloneFile for T {}
pub trait BaseFsCopy {
#[doc(hidden)]
fn base_fs_copy(&self, from: &Path, to: &Path) -> io::Result<u64>;
}
pub trait FsCopy: BaseFsCopy {
#[inline]
fn fs_copy(
&self,
from: impl AsRef<Path>,
to: impl AsRef<Path>,
) -> io::Result<u64> {
self.base_fs_copy(from.as_ref(), to.as_ref())
}
}
impl<T: BaseFsCopy> FsCopy for T {}
#[derive(Default, Debug, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(default, rename_all = "camelCase"))]
#[non_exhaustive] pub struct CreateDirOptions {
pub recursive: bool,
pub mode: Option<u32>,
}
impl CreateDirOptions {
pub fn new() -> Self {
Self::default()
}
pub fn new_recursive() -> Self {
Self {
recursive: true,
..Default::default()
}
}
#[inline]
pub fn recursive(&mut self) -> &mut Self {
self.recursive = true;
self
}
#[inline]
pub fn mode(&mut self, mode: u32) -> &mut Self {
self.mode = Some(mode);
self
}
}
pub trait BaseFsCreateDir {
#[doc(hidden)]
fn base_fs_create_dir(
&self,
path: &Path,
options: &CreateDirOptions,
) -> io::Result<()>;
}
pub trait FsCreateDir: BaseFsCreateDir {
fn fs_create_dir(
&self,
path: impl AsRef<Path>,
options: &CreateDirOptions,
) -> io::Result<()> {
self.base_fs_create_dir(path.as_ref(), options)
}
}
impl<T: BaseFsCreateDir> FsCreateDir for T {}
pub trait FsCreateDirAll: BaseFsCreateDir {
fn fs_create_dir_all(&self, path: impl AsRef<Path>) -> io::Result<()> {
self.base_fs_create_dir(
path.as_ref(),
&CreateDirOptions {
recursive: true,
mode: None,
},
)
}
}
impl<T: BaseFsCreateDir> FsCreateDirAll for T {}
pub trait BaseFsHardLink {
#[doc(hidden)]
fn base_fs_hard_link(&self, src: &Path, dst: &Path) -> io::Result<()>;
}
pub trait FsHardLink: BaseFsHardLink {
fn fs_hard_link(
&self,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
) -> io::Result<()> {
self.base_fs_hard_link(src.as_ref(), dst.as_ref())
}
}
impl<T: BaseFsHardLink> FsHardLink for T {}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FileType {
File,
Dir,
Symlink,
Unknown,
}
impl FileType {
pub fn is_dir(&self) -> bool {
*self == Self::Dir
}
pub fn is_file(&self) -> bool {
*self == Self::File
}
pub fn is_symlink(&self) -> bool {
*self == Self::Symlink
}
}
impl From<std::fs::FileType> for FileType {
fn from(file_type: std::fs::FileType) -> Self {
if file_type.is_file() {
FileType::File
} else if file_type.is_dir() {
FileType::Dir
} else if file_type.is_symlink() {
FileType::Symlink
} else {
FileType::Unknown
}
}
}
#[allow(clippy::len_without_is_empty)]
pub trait FsMetadataValue: std::fmt::Debug {
fn file_type(&self) -> FileType;
fn len(&self) -> u64;
fn accessed(&self) -> io::Result<SystemTime>;
fn created(&self) -> io::Result<SystemTime>;
fn changed(&self) -> io::Result<SystemTime>;
fn modified(&self) -> io::Result<SystemTime>;
fn dev(&self) -> io::Result<u64>;
fn ino(&self) -> io::Result<u64>;
fn mode(&self) -> io::Result<u32>;
fn nlink(&self) -> io::Result<u64>;
fn uid(&self) -> io::Result<u32>;
fn gid(&self) -> io::Result<u32>;
fn rdev(&self) -> io::Result<u64>;
fn blksize(&self) -> io::Result<u64>;
fn blocks(&self) -> io::Result<u64>;
fn is_block_device(&self) -> io::Result<bool>;
fn is_char_device(&self) -> io::Result<bool>;
fn is_fifo(&self) -> io::Result<bool>;
fn is_socket(&self) -> io::Result<bool>;
fn file_attributes(&self) -> io::Result<u32>;
}
pub trait BaseFsMetadata {
type Metadata: FsMetadataValue;
#[doc(hidden)]
fn base_fs_metadata(&self, path: &Path) -> io::Result<Self::Metadata>;
#[doc(hidden)]
fn base_fs_symlink_metadata(&self, path: &Path)
-> io::Result<Self::Metadata>;
#[doc(hidden)]
fn base_fs_exists(&self, path: &Path) -> io::Result<bool> {
match self.base_fs_symlink_metadata(path) {
Ok(_) => Ok(true),
Err(err) => {
if err.kind() == ErrorKind::NotFound {
Ok(false)
} else {
Err(err)
}
}
}
}
#[doc(hidden)]
fn base_fs_exists_no_err(&self, path: &Path) -> bool {
self.base_fs_exists(path).unwrap_or(false)
}
}
pub trait FsMetadata: BaseFsMetadata {
#[inline]
fn fs_metadata(&self, path: impl AsRef<Path>) -> io::Result<Self::Metadata> {
self.base_fs_metadata(path.as_ref())
}
#[inline]
fn fs_symlink_metadata(
&self,
path: impl AsRef<Path>,
) -> io::Result<Self::Metadata> {
self.base_fs_symlink_metadata(path.as_ref())
}
#[inline]
fn fs_is_file(&self, path: impl AsRef<Path>) -> io::Result<bool> {
Ok(self.fs_metadata(path)?.file_type() == FileType::File)
}
#[inline]
fn fs_is_file_no_err(&self, path: impl AsRef<Path>) -> bool {
self.fs_is_file(path).unwrap_or(false)
}
#[inline]
fn fs_is_dir(&self, path: impl AsRef<Path>) -> io::Result<bool> {
Ok(self.fs_metadata(path)?.file_type() == FileType::Dir)
}
#[inline]
fn fs_is_dir_no_err(&self, path: impl AsRef<Path>) -> bool {
self.fs_is_dir(path).unwrap_or(false)
}
#[inline]
fn fs_exists(&self, path: impl AsRef<Path>) -> io::Result<bool> {
self.base_fs_exists(path.as_ref())
}
#[inline]
fn fs_exists_no_err(&self, path: impl AsRef<Path>) -> bool {
self.base_fs_exists_no_err(path.as_ref())
}
#[inline]
fn fs_is_symlink(&self, path: impl AsRef<Path>) -> io::Result<bool> {
Ok(self.fs_symlink_metadata(path)?.file_type() == FileType::Symlink)
}
#[inline]
fn fs_is_symlink_no_err(&self, path: impl AsRef<Path>) -> bool {
self.fs_is_symlink(path).unwrap_or(false)
}
}
impl<T: BaseFsMetadata> FsMetadata for T {}
pub trait FsFile:
std::io::Read
+ std::io::Write
+ std::io::Seek
+ FsFileIsTerminal
+ FsFileLock
+ FsFileSetPermissions
+ FsFileSetTimes
+ FsFileSetLen
+ FsFileSyncAll
+ FsFileSyncData
+ FsFileAsRaw
{
}
pub trait BaseFsOpen {
type File: FsFile;
#[doc(hidden)]
fn base_fs_open(
&self,
path: &Path,
options: &OpenOptions,
) -> io::Result<Self::File>;
}
pub trait FsOpen: BaseFsOpen {
#[inline]
fn fs_open(
&self,
path: impl AsRef<Path>,
options: &OpenOptions,
) -> io::Result<Self::File> {
self.base_fs_open(path.as_ref(), options)
}
}
impl<T: BaseFsOpen> FsOpen for T {}
pub trait BaseFsRead {
#[doc(hidden)]
fn base_fs_read(&self, path: &Path) -> io::Result<Cow<'static, [u8]>>;
}
pub trait FsRead: BaseFsRead {
#[inline]
fn fs_read(&self, path: impl AsRef<Path>) -> io::Result<Cow<'static, [u8]>> {
self.base_fs_read(path.as_ref())
}
fn fs_read_to_string(
&self,
path: impl AsRef<Path>,
) -> io::Result<Cow<'static, str>> {
let bytes = self.fs_read(path)?;
match bytes {
Cow::Borrowed(bytes) => str::from_utf8(bytes)
.map(Cow::Borrowed)
.map_err(|e| e.to_string()),
Cow::Owned(bytes) => String::from_utf8(bytes)
.map(Cow::Owned)
.map_err(|e| e.to_string()),
}
.map_err(|error_text| Error::new(ErrorKind::InvalidData, error_text))
}
fn fs_read_to_string_lossy(
&self,
path: impl AsRef<Path>,
) -> io::Result<Cow<'static, str>> {
#[inline(always)]
fn string_from_utf8_lossy(buf: Vec<u8>) -> String {
match String::from_utf8_lossy(&buf) {
Cow::Owned(s) => s,
Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(buf) },
}
}
let bytes = self.fs_read(path)?;
match bytes {
Cow::Borrowed(bytes) => Ok(String::from_utf8_lossy(bytes)),
Cow::Owned(bytes) => Ok(Cow::Owned(string_from_utf8_lossy(bytes))),
}
}
}
impl<T: BaseFsRead> FsRead for T {}
pub trait FsDirEntry: std::fmt::Debug {
type Metadata: FsMetadataValue;
fn file_name(&self) -> Cow<OsStr>;
fn file_type(&self) -> io::Result<FileType>;
fn metadata(&self) -> io::Result<Self::Metadata>;
fn path(&self) -> Cow<Path>;
}
pub trait BaseFsReadDir {
type ReadDirEntry: FsDirEntry + 'static;
#[doc(hidden)]
fn base_fs_read_dir(
&self,
path: &Path,
) -> io::Result<Box<dyn Iterator<Item = io::Result<Self::ReadDirEntry>> + '_>>;
}
pub trait FsReadDir: BaseFsReadDir {
#[inline]
fn fs_read_dir(
&self,
path: impl AsRef<Path>,
) -> io::Result<Box<dyn Iterator<Item = io::Result<Self::ReadDirEntry>> + '_>>
{
self.base_fs_read_dir(path.as_ref())
}
}
impl<T: BaseFsReadDir> FsReadDir for T {}
pub trait BaseFsReadLink {
#[doc(hidden)]
fn base_fs_read_link(&self, path: &Path) -> io::Result<PathBuf>;
}
pub trait FsReadLink: BaseFsReadLink {
#[inline]
fn fs_read_link(&self, path: impl AsRef<Path>) -> io::Result<PathBuf> {
self.base_fs_read_link(path.as_ref())
}
}
impl<T: BaseFsReadLink> FsReadLink for T {}
pub trait BaseFsRemoveDir {
#[doc(hidden)]
fn base_fs_remove_dir(&self, path: &Path) -> io::Result<()>;
}
pub trait FsRemoveDir: BaseFsRemoveDir {
#[inline]
fn fs_remove_dir(&self, path: impl AsRef<Path>) -> io::Result<()> {
self.base_fs_remove_dir(path.as_ref())
}
}
impl<T: BaseFsRemoveDir> FsRemoveDir for T {}
pub trait BaseFsRemoveDirAll {
#[doc(hidden)]
fn base_fs_remove_dir_all(&self, path: &Path) -> io::Result<()>;
}
pub trait FsRemoveDirAll: BaseFsRemoveDirAll {
#[inline]
fn fs_remove_dir_all(&self, path: impl AsRef<Path>) -> io::Result<()> {
self.base_fs_remove_dir_all(path.as_ref())
}
}
impl<T: BaseFsRemoveDirAll> FsRemoveDirAll for T {}
pub trait BaseFsRemoveFile {
#[doc(hidden)]
fn base_fs_remove_file(&self, path: &Path) -> io::Result<()>;
}
pub trait FsRemoveFile: BaseFsRemoveFile {
#[inline]
fn fs_remove_file(&self, path: impl AsRef<Path>) -> io::Result<()> {
self.base_fs_remove_file(path.as_ref())
}
}
impl<T: BaseFsRemoveFile> FsRemoveFile for T {}
pub trait BaseFsRename {
#[doc(hidden)]
fn base_fs_rename(&self, from: &Path, to: &Path) -> io::Result<()>;
}
pub trait FsRename: BaseFsRename {
#[inline]
fn fs_rename(
&self,
from: impl AsRef<Path>,
to: impl AsRef<Path>,
) -> io::Result<()> {
self.base_fs_rename(from.as_ref(), to.as_ref())
}
}
impl<T: BaseFsRename> FsRename for T {}
pub trait BaseFsSetFileTimes {
#[doc(hidden)]
fn base_fs_set_file_times(
&self,
path: &Path,
atime: SystemTime,
mtime: SystemTime,
) -> io::Result<()>;
}
pub trait FsSetFileTimes: BaseFsSetFileTimes {
#[inline]
fn fs_set_file_times(
&self,
path: impl AsRef<Path>,
atime: SystemTime,
mtime: SystemTime,
) -> io::Result<()> {
self.base_fs_set_file_times(path.as_ref(), atime, mtime)
}
}
impl<T: BaseFsSetFileTimes> FsSetFileTimes for T {}
pub trait BaseFsSetSymlinkFileTimes {
#[doc(hidden)]
fn base_fs_set_symlink_file_times(
&self,
path: &Path,
atime: SystemTime,
mtime: SystemTime,
) -> io::Result<()>;
}
pub trait FsSetSymlinkFileTimes: BaseFsSetSymlinkFileTimes {
#[inline]
fn fs_set_symlink_file_times(
&self,
path: impl AsRef<Path>,
atime: SystemTime,
mtime: SystemTime,
) -> io::Result<()> {
self.base_fs_set_symlink_file_times(path.as_ref(), atime, mtime)
}
}
impl<T: BaseFsSetSymlinkFileTimes> FsSetSymlinkFileTimes for T {}
pub trait BaseFsSetPermissions {
#[doc(hidden)]
fn base_fs_set_permissions(&self, path: &Path, mode: u32) -> io::Result<()>;
}
pub trait FsSetPermissions: BaseFsSetPermissions {
fn fs_set_permissions(
&self,
path: impl AsRef<Path>,
mode: u32,
) -> io::Result<()> {
self.base_fs_set_permissions(path.as_ref(), mode)
}
}
impl<T: BaseFsSetPermissions> FsSetPermissions for T {}
pub trait BaseFsSymlinkDir {
#[doc(hidden)]
fn base_fs_symlink_dir(&self, original: &Path, link: &Path)
-> io::Result<()>;
}
pub trait FsSymlinkDir: BaseFsSymlinkDir {
#[inline]
fn fs_symlink_dir(
&self,
original: impl AsRef<Path>,
link: impl AsRef<Path>,
) -> io::Result<()> {
self.base_fs_symlink_dir(original.as_ref(), link.as_ref())
}
}
impl<T: BaseFsSymlinkDir> FsSymlinkDir for T {}
pub trait BaseFsSymlinkFile {
#[doc(hidden)]
fn base_fs_symlink_file(
&self,
original: &Path,
link: &Path,
) -> io::Result<()>;
}
pub trait FsSymlinkFile: BaseFsSymlinkFile {
#[inline]
fn fs_symlink_file(
&self,
original: impl AsRef<Path>,
link: impl AsRef<Path>,
) -> io::Result<()> {
self.base_fs_symlink_file(original.as_ref(), link.as_ref())
}
}
impl<T: BaseFsSymlinkFile> FsSymlinkFile for T {}
pub trait BaseFsWrite {
#[doc(hidden)]
fn base_fs_write(&self, path: &Path, data: &[u8]) -> io::Result<()>;
}
pub trait FsWrite: BaseFsWrite {
#[inline]
fn fs_write(
&self,
path: impl AsRef<Path>,
data: impl AsRef<[u8]>,
) -> io::Result<()> {
self.base_fs_write(path.as_ref(), data.as_ref())
}
}
impl<T: BaseFsWrite> FsWrite for T {}
pub trait FsFileAsRaw {
#[cfg(windows)]
fn fs_file_as_raw_handle(&self) -> Option<std::os::windows::io::RawHandle>;
#[cfg(unix)]
fn fs_file_as_raw_fd(&self) -> Option<std::os::fd::RawFd>;
}
pub trait FsFileIsTerminal {
fn fs_file_is_terminal(&self) -> bool;
}
pub enum FsFileLockMode {
Shared,
Exclusive,
}
pub trait FsFileLock {
fn fs_file_lock(&mut self, mode: FsFileLockMode) -> io::Result<()>;
fn fs_file_try_lock(&mut self, mode: FsFileLockMode) -> io::Result<()>;
fn fs_file_unlock(&mut self) -> io::Result<()>;
}
pub trait FsFileSetLen {
fn fs_file_set_len(&mut self, size: u64) -> io::Result<()>;
}
pub trait FsFileSetPermissions {
fn fs_file_set_permissions(&mut self, mode: u32) -> io::Result<()>;
}
#[derive(Debug, Clone, Default)]
pub struct FsFileTimes {
pub accessed: Option<SystemTime>,
pub modified: Option<SystemTime>,
}
impl FsFileTimes {
pub fn new() -> Self {
Self::default()
}
pub fn accessed(&mut self, accessed: SystemTime) -> &mut Self {
self.accessed = Some(accessed);
self
}
pub fn modified(&mut self, accessed: SystemTime) -> &mut Self {
self.modified = Some(accessed);
self
}
}
pub trait FsFileSetTimes {
fn fs_file_set_times(&mut self, times: FsFileTimes) -> io::Result<()>;
}
pub trait FsFileSyncAll {
fn fs_file_sync_all(&mut self) -> io::Result<()>;
}
pub trait FsFileSyncData {
fn fs_file_sync_data(&mut self) -> io::Result<()>;
}
pub trait SystemTimeNow {
fn sys_time_now(&self) -> std::time::SystemTime;
}
pub trait SystemRandom {
fn sys_random(&self, buf: &mut [u8]) -> io::Result<()>;
fn sys_random_u8(&self) -> io::Result<u8> {
let mut buf = [0; 1];
self.sys_random(&mut buf)?;
Ok(buf[0])
}
fn sys_random_u32(&self) -> io::Result<u32> {
let mut buf = [0; 4];
self.sys_random(&mut buf)?;
Ok(u32::from_le_bytes(buf))
}
fn sys_random_u64(&self) -> io::Result<u64> {
let mut buf = [0; 8];
self.sys_random(&mut buf)?;
Ok(u64::from_le_bytes(buf))
}
}
pub trait ThreadSleep {
fn thread_sleep(&self, duration: std::time::Duration);
}