238 lines
5.7 KiB
Rust
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
|
|
}
|