diff --git a/Cargo.toml b/Cargo.toml index f0e69f4..74ad8bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,42 +41,40 @@ required-features = [ "caldav" ] [dependencies] bytes = "1.0.1" dyn-clone = "1" -futures-util = "0.3.16" +futures-util = { version = "0.3.16", default-features = false, features = ["alloc"] } futures-channel = "0.3.16" headers = "0.4.0" htmlescape = "0.3.1" http = "1.0.0" http-body = "1.0.0" http-body-util = "0.1.0" -lazy_static = "1.4.0" libc = { version = "0.2.0", optional = true } log = "0.4.0" -lru = { version = "0.14.0", optional = true } +lru = { version = "0.16.0", optional = true } mime_guess = "2.0.0" parking_lot = { version = "0.12.0", optional = true } percent-encoding = "2.1.0" -pin-project = "1.0.4" -pin-utils = "0.1.0" -regex = "1.4.0" +pin-project-lite = "0.2.16" tokio = { version = "1.3.0", features = [ "rt-multi-thread", "io-util", "net", "time", "sync" ] } time = { version = "0.3.2", default-features = false, features = [ "macros", "formatting" ] } url = "2.2.0" uuid = { version = "1.1.2", features = ["v4"] } -xml-rs = "0.8.0" -xmltree = "0.11.0" +xml-rs = "1" +xmltree = "0.12.0" -hyper = { version = "1.1.0", optional = true } +hyper = { version = "1.1.0", default-features = false, features = ["server"], optional = true } warp = { version = "0.3.0", optional = true, default-features = false } -actix-web = { version = "4.0.0-beta.15", optional = true } +actix-web = { version = "4.0.0-beta.15", default-features = false, optional = true } reflink-copy = { version = "0.1.14", optional = true } icalendar = { version = "0.17.1", optional = true } -chrono = { version = "0.4", optional = true } +chrono = { version = "0.4", default-features = false, features = ["now"], optional = true } derive-where = "1.6.0" [dev-dependencies] clap = { version = "4.0.0", features = ["derive"] } env_logger = "0.11.0" +actix-web = { version = "4.0.0-beta.15", default-features = false, features = ["macros"] } hyper = { version = "1.1.0", features = ["http1", "server"] } hyper-util = { version = "0.1.2", features = ["tokio"] } tokio = { version = "1.3.0", features = ["full"] } -axum = { version = "0.8", features = [] } \ No newline at end of file +axum = { version = "0.8", features = [] } diff --git a/src/actix.rs b/src/actix.rs index dfc997c..3a788e8 100644 --- a/src/actix.rs +++ b/src/actix.rs @@ -14,7 +14,7 @@ //! use std::{ convert::TryInto, - io, + future, io, pin::Pin, task::{Context, Poll}, }; @@ -23,8 +23,8 @@ use actix_web::body::BoxBody; use actix_web::error::PayloadError; use actix_web::{Error, FromRequest, HttpRequest, HttpResponse, dev}; use bytes::Bytes; -use futures_util::{Stream, future}; -use pin_project::pin_project; +use futures_util::Stream; +use pin_project_lite::pin_project; /// http::Request compatibility. /// @@ -71,13 +71,14 @@ impl FromRequest for DavRequest { } } -/// Body type for `DavRequest`. -/// -/// It wraps actix's `PayLoad` and implements `http_body::Body`. -#[pin_project] -pub struct DavBody { - #[pin] - body: dev::Payload, +pin_project! { + /// Body type for `DavRequest`. + /// + /// It wraps actix's `PayLoad` and implements `http_body::Body`. + pub struct DavBody { + #[pin] + body: dev::Payload, + } } impl http_body::Body for DavBody { diff --git a/src/body.rs b/src/body.rs index d713d74..763014d 100644 --- a/src/body.rs +++ b/src/body.rs @@ -8,6 +8,7 @@ use std::task::{Context, Poll}; use bytes::{Buf, Bytes}; use futures_util::stream::Stream; use http_body::Body as HttpBody; +use pin_project_lite::pin_project; use crate::async_stream::AsyncStream; @@ -91,15 +92,14 @@ impl From> for Body { } } -use pin_project::pin_project; - -// -// A struct that contains a Stream, and implements http_body::Body. -// -#[pin_project] -pub(crate) struct StreamBody { - #[pin] - body: B, +pin_project! { + // + // A struct that contains a Stream, and implements http_body::Body. + // + pub(crate) struct StreamBody { + #[pin] + body: B, + } } impl HttpBody for StreamBody diff --git a/src/davhandler.rs b/src/davhandler.rs index 1099310..1019d85 100644 --- a/src/davhandler.rs +++ b/src/davhandler.rs @@ -4,6 +4,7 @@ // use std::error::Error as StdError; use std::io; +use std::pin::pin; use std::sync::Arc; use bytes::{self, buf::Buf}; @@ -368,7 +369,7 @@ where ReqError: StdError + Send + Sync + 'static, { let mut data = Vec::new(); - pin_utils::pin_mut!(body); + let mut body = pin!(body); while let Some(res) = body.frame().await { let mut data_frame = res.map_err(|_| { diff --git a/src/davheaders.rs b/src/davheaders.rs index a4351df..2060bfd 100644 --- a/src/davheaders.rs +++ b/src/davheaders.rs @@ -4,25 +4,21 @@ use std::str::FromStr; use headers::Header; use http::header::{HeaderName, HeaderValue}; -use lazy_static::lazy_static; -use regex::Regex; +use url::Url; use crate::fs::DavMetaData; -lazy_static! { - static ref RE_URL: Regex = Regex::new(r"https?://[^/]*([^#?]+).*$").unwrap(); - pub static ref DEPTH: HeaderName = HeaderName::from_static("depth"); - pub static ref TIMEOUT: HeaderName = HeaderName::from_static("timeout"); - pub static ref OVERWRITE: HeaderName = HeaderName::from_static("overwrite"); - pub static ref DESTINATION: HeaderName = HeaderName::from_static("destination"); - pub static ref ETAG: HeaderName = HeaderName::from_static("etag"); - pub static ref IF_RANGE: HeaderName = HeaderName::from_static("if-range"); - pub static ref IF_MATCH: HeaderName = HeaderName::from_static("if-match"); - pub static ref IF_NONE_MATCH: HeaderName = HeaderName::from_static("if-none-match"); - pub static ref X_UPDATE_RANGE: HeaderName = HeaderName::from_static("x-update-range"); - pub static ref IF: HeaderName = HeaderName::from_static("if"); - pub static ref CONTENT_LANGUAGE: HeaderName = HeaderName::from_static("content-language"); -} +pub static DEPTH: HeaderName = HeaderName::from_static("depth"); +pub static TIMEOUT: HeaderName = HeaderName::from_static("timeout"); +pub static OVERWRITE: HeaderName = HeaderName::from_static("overwrite"); +pub static DESTINATION: HeaderName = HeaderName::from_static("destination"); +pub static ETAG: HeaderName = HeaderName::from_static("etag"); +pub static IF_RANGE: HeaderName = HeaderName::from_static("if-range"); +pub static IF_MATCH: HeaderName = HeaderName::from_static("if-match"); +pub static IF_NONE_MATCH: HeaderName = HeaderName::from_static("if-none-match"); +pub static X_UPDATE_RANGE: HeaderName = HeaderName::from_static("x-update-range"); +pub static IF: HeaderName = HeaderName::from_static("if"); +pub static CONTENT_LANGUAGE: HeaderName = HeaderName::from_static("content-language"); // helper. fn one<'i, I>(values: &mut I) -> Result<&'i HeaderValue, headers::Error> @@ -49,9 +45,7 @@ fn map_invalid(_e: impl std::error::Error) -> headers::Error { macro_rules! header { ($tname:ident, $hname:ident, $sname:expr_2021) => { - lazy_static! { - pub static ref $hname: HeaderName = HeaderName::from_static($sname); - } + pub static $hname: HeaderName = HeaderName::from_static($sname); #[derive(Debug, Clone, PartialEq)] pub struct $tname(pub String); @@ -256,10 +250,8 @@ impl Header for Destination { if s.starts_with('/') { return Ok(Destination(s.to_string())); } - if let Some(caps) = RE_URL.captures(s) - && let Some(path) = caps.get(1) - { - return Ok(Destination(path.as_str().to_string())); + if let Ok(url) = s.parse::() { + return Ok(Destination(url.path().to_string())); } Err(invalid()) } diff --git a/src/fakels.rs b/src/fakels.rs index 2378307..83dc916 100644 --- a/src/fakels.rs +++ b/src/fakels.rs @@ -12,9 +12,10 @@ //! If: headers always succeeds, and nothing is every really locked. //! //! `FakeLs` implements such a fake locksystem. +use std::future; use std::time::{Duration, SystemTime}; -use futures_util::{FutureExt, future}; +use futures_util::FutureExt; use uuid::Uuid; use xmltree::Element; diff --git a/src/fs.rs b/src/fs.rs index a674d40..ab10ec7 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -4,12 +4,13 @@ //! filesystem backend. Otherwise, just use 'LocalFs' or 'MemFs'. //! use std::fmt::Debug; +use std::future::{self, Future}; use std::io::SeekFrom; use std::pin::Pin; use std::time::{SystemTime, UNIX_EPOCH}; use dyn_clone::{DynClone, clone_trait_object}; -use futures_util::{Future, FutureExt, Stream, TryFutureExt, future}; +use futures_util::{FutureExt, Stream, TryFutureExt}; use http::StatusCode; use crate::davpath::DavPath; @@ -664,19 +665,25 @@ pub trait DavDirEntry: Send + Sync { /// expensive and there is a cheaper way to provide the same info /// (e.g. dirent.d_type in unix filesystems). fn is_dir(&'_ self) -> FsFuture<'_, bool> { - Box::pin(self.metadata().and_then(|meta| future::ok(meta.is_dir()))) + Box::pin( + self.metadata() + .and_then(|meta| future::ready(Ok(meta.is_dir()))), + ) } /// Likewise. Default: `!is_dir()`. fn is_file(&'_ self) -> FsFuture<'_, bool> { - Box::pin(self.metadata().and_then(|meta| future::ok(meta.is_file()))) + Box::pin( + self.metadata() + .and_then(|meta| future::ready(Ok(meta.is_file()))), + ) } /// Likewise. Default: `false`. fn is_symlink(&'_ self) -> FsFuture<'_, bool> { Box::pin( self.metadata() - .and_then(|meta| future::ok(meta.is_symlink())), + .and_then(|meta| future::ready(Ok(meta.is_symlink()))), ) } } diff --git a/src/handle_props.rs b/src/handle_props.rs index 744c107..f4b20f5 100644 --- a/src/handle_props.rs +++ b/src/handle_props.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::collections::HashMap; use std::convert::TryFrom; use std::io::{self, Cursor}; +use std::sync::LazyLock; use futures_util::{FutureExt, StreamExt, future::BoxFuture}; use headers::HeaderMapExt; @@ -129,11 +130,9 @@ const MS_ALLPROP_STR: &[&str] = &[ "Z:Win32LastModifiedTime", ]; -lazy_static! { - static ref ALLPROP: Vec = init_staticprop(ALLPROP_STR); - static ref MS_ALLPROP: Vec = init_staticprop(MS_ALLPROP_STR); - static ref PROPNAME: Vec = init_staticprop(PROPNAME_STR); -} +static ALLPROP: LazyLock> = LazyLock::new(|| init_staticprop(ALLPROP_STR)); +static MS_ALLPROP: LazyLock> = LazyLock::new(|| init_staticprop(MS_ALLPROP_STR)); +static PROPNAME: LazyLock> = LazyLock::new(|| init_staticprop(PROPNAME_STR)); type Emitter = EventWriter; type Sender = crate::async_stream::Sender; diff --git a/src/handle_put.rs b/src/handle_put.rs index c24b60f..41a3d15 100644 --- a/src/handle_put.rs +++ b/src/handle_put.rs @@ -1,6 +1,7 @@ use std::any::Any; use std::error::Error as StdError; use std::io; +use std::pin::pin; use bytes::{Buf, Bytes}; use headers::HeaderMapExt; @@ -233,7 +234,7 @@ impl DavInner { res.headers_mut() .typed_insert(headers::AcceptRanges::bytes()); - pin_utils::pin_mut!(body); + let mut body = pin!(body); // loop, read body, write to file. let mut total = 0u64; diff --git a/src/lib.rs b/src/lib.rs index da0855b..10bc213 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -188,8 +188,6 @@ #[macro_use] extern crate log; -#[macro_use] -extern crate lazy_static; mod async_stream; mod conditional; diff --git a/src/localfs.rs b/src/localfs.rs index b3c79d4..c28363d 100644 --- a/src/localfs.rs +++ b/src/localfs.rs @@ -6,7 +6,7 @@ use std::any::Any; use std::collections::VecDeque; -use std::future::Future; +use std::future::{self, Future}; use std::io::{self, Read, Seek, SeekFrom, Write}; #[cfg(unix)] use std::os::unix::{ @@ -17,14 +17,14 @@ use std::os::unix::{ use std::os::windows::prelude::*; use std::path::{Path, PathBuf}; use std::pin::Pin; +use std::pin::pin; use std::sync::Arc; use std::sync::atomic::{AtomicU32, Ordering}; use std::task::{Context, Poll}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use bytes::{Buf, Bytes, BytesMut}; -use futures_util::{FutureExt, Stream, future, future::BoxFuture}; -use pin_utils::pin_mut; +use futures_util::{FutureExt, Stream, future::BoxFuture}; use tokio::task; use libc; @@ -553,8 +553,7 @@ impl Stream for LocalFsReadDir { } // Poll the future. - let fut = this.fut.as_mut().unwrap(); - pin_mut!(fut); + let mut fut = pin!(this.fut.as_mut().unwrap()); match Pin::new(&mut fut).poll(cx) { Poll::Ready(batch) => { this.fut.take(); diff --git a/src/localfs_macos.rs b/src/localfs_macos.rs index 5aa0f8b..cd6bc14 100644 --- a/src/localfs_macos.rs +++ b/src/localfs_macos.rs @@ -13,7 +13,7 @@ use std::num::NonZeroUsize; #[cfg(unix)] use std::os::unix::ffi::OsStrExt; use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::LazyLock; use std::sync::atomic::{AtomicUsize, Ordering}; use std::thread; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -29,9 +29,7 @@ const DU_CACHE_ENTRIES: usize = 4096; const DU_CACHE_MAX_AGE: u64 = 60; const DU_CACHE_SLEEP_MS: u64 = 10037; -lazy_static! { - static ref DU_CACHE: Arc = Arc::new(DUCache::new(DU_CACHE_ENTRIES)); -} +static DU_CACHE: LazyLock = LazyLock::new(|| DUCache::new(DU_CACHE_ENTRIES)); static DIR_ID: AtomicUsize = AtomicUsize::new(1); diff --git a/src/localfs_windows.rs b/src/localfs_windows.rs index 463851c..7e348a3 100644 --- a/src/localfs_windows.rs +++ b/src/localfs_windows.rs @@ -8,7 +8,7 @@ use std::fs; use std::io::ErrorKind; use std::num::NonZeroUsize; use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::LazyLock; use std::thread; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -21,9 +21,7 @@ const CACHE_ENTRIES: usize = 4096; const CACHE_MAX_AGE: u64 = 15 * 60; const CACHE_SLEEP_MS: u64 = 30059; -lazy_static! { - static ref CACHE: Arc = Arc::new(Cache::new(CACHE_ENTRIES)); -} +static CACHE: LazyLock = LazyLock::new(|| Cache::new(CACHE_ENTRIES)); // Do a case-insensitive path lookup. pub(crate) fn resolve(base: impl Into, path: &DavPath) -> PathBuf { @@ -43,7 +41,7 @@ pub(crate) fn resolve(base: impl Into, path: &DavPath) -> PathBuf { None => return fullpath, }; - // deref in advance: first lazy_static, then Arc. + // deref in advance: first LazyLock, then Arc. let cache = &*CACHE; // In the cache? diff --git a/src/ls.rs b/src/ls.rs index 3def7a8..8243da4 100644 --- a/src/ls.rs +++ b/src/ls.rs @@ -9,11 +9,11 @@ //! use crate::davpath::DavPath; use std::fmt::Debug; +use std::future::Future; use std::pin::Pin; use std::time::{Duration, SystemTime}; use dyn_clone::{DynClone, clone_trait_object}; -use futures_util::Future; use xmltree::Element; /// Type of the locks returned by DavLockSystem methods. diff --git a/src/memls.rs b/src/memls.rs index c82f9f3..31498d6 100644 --- a/src/memls.rs +++ b/src/memls.rs @@ -7,10 +7,11 @@ //! it in your handler struct, and clone() it every time you pass //! it to the DavHandler. As a MemLs struct is just a handle, cloning is cheap. use std::collections::HashMap; +use std::future; use std::sync::{Arc, Mutex}; use std::time::{Duration, SystemTime}; -use futures_util::{FutureExt, future}; +use futures_util::FutureExt; use uuid::Uuid; use xmltree::Element;