actix-fs/src/lib.rs
2020-06-06 14:30:37 -05:00

238 lines
5.7 KiB
Rust

//! # Actix FS
//! _Asyncronous filesystem operations for actix-based systems_
//!
//! ## Usage
//!
//! ```rust
//! use std::io::SeekFrom;
//!
//! #[actix_rt::main]
//! async fn main() -> Result<(), anyhow::Error> {
//! let file = actix_fs::file::open("tests/read.txt").await?;
//! let (file, position) = actix_fs::file::seek(file, SeekFrom::Start(7)).await?;
//! let bytes = actix_fs::file::read(file).await?;
//!
//! assert!(position == 7);
//! assert!(bytes.as_ref() == b"World!\n");
//! Ok(())
//! }
//! ```
//!
//! ### Contributing
//! Unless otherwise stated, all contributions to this project will be licensed under the CSL with
//! the exceptions listed in the License section of this file.
//!
//! ### License
//! This work is licensed under the Cooperative Software License. This is not a Free Software
//! License, but may be considered a "source-available License." For most hobbyists, self-employed
//! developers, worker-owned companies, and cooperatives, this software can be used in most
//! projects so long as this software is distributed under the terms of the CSL. For more
//! information, see the provided LICENSE file. If none exists, the license can be found online
//! [here](https://lynnesbian.space/csl/). If you are a free software project and wish to use this
//! software under the terms of the GNU Affero General Public License, please contact me at
//! [asonix@asonix.dog](mailto:asonix@asonix.dog) and we can sort that out. If you wish to use this
//! project under any other license, especially in proprietary software, the answer is likely no.
//!
//! Actix FS is currently licensed under the AGPL to the Lemmy project, found
//! at [github.com/LemmyNet/lemmy](https://github.com/LemmyNet/lemmy)
use actix_threadpool::run;
use bytes::Bytes;
use futures::stream::Stream;
use std::{
fs, io,
path::{Path, PathBuf},
};
pub mod file;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("{0}")]
Io(#[from] io::Error),
#[error("Task canceled")]
Canceled,
}
impl Error {
pub fn kind(&self) -> Option<io::ErrorKind> {
match self {
Error::Io(ref io) => Some(io.kind()),
_ => None,
}
}
}
impl From<std::str::Utf8Error> for Error {
fn from(e: std::str::Utf8Error) -> Self {
Error::Io(io::Error::new(io::ErrorKind::InvalidInput, e))
}
}
pub async fn canonicalize<P>(path: P) -> Result<PathBuf, Error>
where
P: AsRef<Path> + Send + 'static,
{
let path = run(move || fs::canonicalize(path)).await?;
Ok(path)
}
pub async fn copy<P, Q>(from: P, to: Q) -> Result<u64, Error>
where
P: AsRef<Path> + Send + 'static,
Q: AsRef<Path> + Send + 'static,
{
let bytes = run(move || fs::copy(from, to)).await?;
Ok(bytes)
}
pub async fn create_dir<P>(path: P) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::create_dir(path)).await?;
Ok(())
}
pub async fn create_dir_all<P>(path: P) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::create_dir_all(path)).await?;
Ok(())
}
pub async fn hard_link<P, Q>(src: P, dst: Q) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
Q: AsRef<Path> + Send + 'static,
{
run(move || fs::hard_link(src, dst)).await?;
Ok(())
}
pub async fn metadata<P>(path: P) -> Result<fs::Metadata, Error>
where
P: AsRef<Path> + Send + 'static,
{
let metadata = run(move || fs::metadata(path)).await?;
Ok(metadata)
}
pub async fn read<P>(path: P) -> Result<Bytes, Error>
where
P: AsRef<Path> + Send + 'static,
{
let f = file::open(path).await?;
file::read(f).await
}
pub async fn read_link<P>(path: P) -> Result<PathBuf, Error>
where
P: AsRef<Path> + Send + 'static,
{
let path = run(move || fs::read_link(path)).await?;
Ok(path)
}
pub async fn read_to_stream<P>(path: P) -> Result<file::FileStream, Error>
where
P: AsRef<Path> + Send + 'static,
{
let f = file::open(path).await?;
file::read_to_stream(f).await
}
pub async fn read_to_string<P>(path: P) -> Result<String, Error>
where
P: AsRef<Path> + Send + 'static,
{
let f = file::open(path).await?;
file::read_to_string(f).await
}
pub async fn remove_dir<P>(path: P) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::remove_dir(path)).await?;
Ok(())
}
pub async fn remove_dir_all<P>(path: P) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::remove_dir_all(path)).await?;
Ok(())
}
pub async fn remove_file<P>(path: P) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::remove_file(path)).await?;
Ok(())
}
pub async fn rename<P, Q>(from: P, to: Q) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
Q: AsRef<Path> + Send + 'static,
{
run(move || fs::rename(from, to)).await?;
Ok(())
}
pub async fn set_permissions<P>(path: P, permissions: fs::Permissions) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
run(move || fs::set_permissions(path, permissions)).await?;
Ok(())
}
pub async fn symlink_metadata<P>(path: P) -> Result<fs::Metadata, Error>
where
P: AsRef<Path> + Send + 'static,
{
let metadata = run(move || fs::symlink_metadata(path)).await?;
Ok(metadata)
}
pub async fn write<P>(path: P, contents: Bytes) -> Result<(), Error>
where
P: AsRef<Path> + Send + 'static,
{
let f = file::create(path).await?;
file::write(f, contents).await
}
pub async fn write_stream<P, S, E>(path: P, stream: S) -> Result<(), E>
where
P: AsRef<Path> + Send + 'static,
S: Stream<Item = Result<Bytes, E>> + Unpin,
E: From<Error> + Unpin,
{
let f = file::create(path).await?;
file::write_stream(f, stream).await
}