diff --git a/Cargo.lock b/Cargo.lock index 2bec99ad..5420d1d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -527,9 +527,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" +checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5" dependencies = [ "clap_builder", "clap_derive", @@ -537,9 +537,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" +checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a" dependencies = [ "anstream", "anstyle", @@ -549,9 +549,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.59" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2348487adcd4631696ced64ccdb40d38ac4d31cae7f2eec8817fcea1b9d1c43c" +checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971" dependencies = [ "clap", ] @@ -1820,9 +1820,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ "once_cell", "wasm-bindgen", @@ -2136,9 +2136,9 @@ dependencies = [ [[package]] name = "moxcms" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692af879e4d9383c0fd9dec15524af6b6977c8bf1c6b278a4526d5341347c574" +checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6" dependencies = [ "num-traits", "pxfm", @@ -3972,9 +3972,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-segmentation" @@ -4149,9 +4149,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ "cfg-if", "once_cell", @@ -4160,25 +4160,11 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", @@ -4189,9 +4175,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4199,31 +4185,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 89ac9f85..7033a0ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ ansi-to-tui = "7.0.0" anyhow = "1.0.100" base64 = "0.22.1" bitflags = { version = "2.10.0", features = [ "serde" ] } -clap = { version = "4.5.50", features = [ "derive" ] } +clap = { version = "4.5.51", features = [ "derive" ] } core-foundation-sys = "0.8.7" crossterm = { version = "0.29.0", features = [ "event-stream" ] } dirs = "6.0.0" diff --git a/yazi-actor/src/mgr/create.rs b/yazi-actor/src/mgr/create.rs index 613a2dcb..978860fd 100644 --- a/yazi-actor/src/mgr/create.rs +++ b/yazi-actor/src/mgr/create.rs @@ -51,7 +51,7 @@ impl Create { && let Some((parent, urn)) = real.pair() { ok_or_not_found!(provider::remove_file(&new).await); - FilesOp::Deleting(parent.into(), [urn.into()].into()).emit(); + FilesOp::Deleting(parent.into(), [urn.to_owned()].into()).emit(); provider::create(&new).await?; } else if let Some(parent) = new.parent() { provider::create_dir_all(parent).await.ok(); @@ -65,7 +65,7 @@ impl Create { && let Some((parent, urn)) = real.pair() { let file = File::new(&real).await?; - FilesOp::Upserting(parent.into(), [(urn.into(), file)].into()).emit(); + FilesOp::Upserting(parent.into(), [(urn.to_owned(), file)].into()).emit(); MgrProxy::reveal(&real); } diff --git a/yazi-actor/src/mgr/hover.rs b/yazi-actor/src/mgr/hover.rs index 06538824..9007d4ba 100644 --- a/yazi-actor/src/mgr/hover.rs +++ b/yazi-actor/src/mgr/hover.rs @@ -26,7 +26,7 @@ impl Actor for Hover { // Turn on tracing if let (Some(h), Some(u)) = (tab.hovered(), opt.urn) - && *h.urn() == u + && h.urn() == u { // `hover(Some)` occurs after user actions, such as create, rename, reveal, etc. // At this point, it's intuitive to track the location of the file regardless. diff --git a/yazi-actor/src/mgr/rename.rs b/yazi-actor/src/mgr/rename.rs index 65aadfa4..02c0d166 100644 --- a/yazi-actor/src/mgr/rename.rs +++ b/yazi-actor/src/mgr/rename.rs @@ -73,7 +73,7 @@ impl Rename { && let Some((parent, urn)) = u.pair() { ok_or_not_found!(provider::rename(&u, &new).await); - FilesOp::Deleting(parent.to_owned(), [urn.into()].into()).emit(); + FilesOp::Deleting(parent.to_owned(), [urn.to_owned()].into()).emit(); } let new = provider::casefold(&new).await?; @@ -81,10 +81,10 @@ impl Rename { let file = File::new(&new).await?; if new_p == old_p { - FilesOp::Upserting(old_p.into(), [(old_n.into(), file)].into()).emit(); + FilesOp::Upserting(old_p.into(), [(old_n.to_owned(), file)].into()).emit(); } else { - FilesOp::Deleting(old_p.into(), [old_n.into()].into()).emit(); - FilesOp::Upserting(new_p.into(), [(new_n.into(), file)].into()).emit(); + FilesOp::Deleting(old_p.into(), [old_n.to_owned()].into()).emit(); + FilesOp::Upserting(new_p.into(), [(new_n.to_owned(), file)].into()).emit(); } MgrProxy::reveal(&new); diff --git a/yazi-actor/src/mgr/reveal.rs b/yazi-actor/src/mgr/reveal.rs index 590d0924..f8f874aa 100644 --- a/yazi-actor/src/mgr/reveal.rs +++ b/yazi-actor/src/mgr/reveal.rs @@ -31,7 +31,7 @@ impl Actor for Reveal { } // Now, we can safely hover on the target - act!(mgr:hover, cx, Some(child.into()))?; + act!(mgr:hover, cx, Some(child.to_owned()))?; act!(mgr:peek, cx)?; act!(mgr:watch, cx)?; diff --git a/yazi-binding/src/urn.rs b/yazi-binding/src/urn.rs index aa321494..d6851486 100644 --- a/yazi-binding/src/urn.rs +++ b/yazi-binding/src/urn.rs @@ -1,26 +1,39 @@ -use std::ops::Deref; +use std::{ops::Deref, path::PathBuf}; use mlua::{ExternalError, FromLua, Lua, UserData, Value}; +use yazi_shared::path::PathBufLike; -pub struct Urn { - inner: yazi_shared::url::UrnBuf, +pub struct Urn { + inner: yazi_shared::url::UrnBuf

, } -impl Deref for Urn { - type Target = yazi_shared::url::UrnBuf; +impl

Deref for Urn

+where + P: PathBufLike, +{ + type Target = yazi_shared::url::UrnBuf

; fn deref(&self) -> &Self::Target { &self.inner } } -impl From for yazi_shared::url::UrnBuf { - fn from(value: Urn) -> Self { value.inner } +impl

From> for yazi_shared::url::UrnBuf

+where + P: PathBufLike, +{ + fn from(value: Urn

) -> Self { value.inner } } -impl Urn { - pub fn new(urn: impl Into) -> Self { Self { inner: urn.into() } } +impl

Urn

+where + P: PathBufLike, +{ + pub fn new(urn: impl Into>) -> Self { Self { inner: urn.into() } } } -impl FromLua for Urn { +impl

FromLua for Urn

+where + P: PathBufLike, +{ fn from_lua(value: Value, _: &Lua) -> mlua::Result { Ok(match value { Value::UserData(ud) => ud.take()?, @@ -29,4 +42,4 @@ impl FromLua for Urn { } } -impl UserData for Urn {} +impl

UserData for Urn

where P: PathBufLike {} diff --git a/yazi-boot/Cargo.toml b/yazi-boot/Cargo.toml index 98230d28..ca4b78ed 100644 --- a/yazi-boot/Cargo.toml +++ b/yazi-boot/Cargo.toml @@ -28,7 +28,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External dependencies clap = { workspace = true } -clap_complete = "4.5.59" +clap_complete = "4.5.60" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.9" vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] } diff --git a/yazi-boot/src/boot.rs b/yazi-boot/src/boot.rs index 7f4e0f3c..a45f1bae 100644 --- a/yazi-boot/src/boot.rs +++ b/yazi-boot/src/boot.rs @@ -38,7 +38,7 @@ impl Boot { }; if provider::metadata(&entry).await.is_ok_and(|m| m.is_file()) { - (parent.into(), child.into()) + (parent.into(), child.to_owned()) } else { (entry, UrnBuf::default()) } diff --git a/yazi-cli/Cargo.toml b/yazi-cli/Cargo.toml index 80599611..bf40c872 100644 --- a/yazi-cli/Cargo.toml +++ b/yazi-cli/Cargo.toml @@ -41,7 +41,7 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" } # External build dependencies anyhow = { workspace = true } clap = { workspace = true } -clap_complete = "4.5.59" +clap_complete = "4.5.60" clap_complete_fig = "4.5.2" clap_complete_nushell = "4.5.9" serde_json = { workspace = true } diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index 200304b7..b7e3cb32 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -121,7 +121,7 @@ impl Folder { if let Some(u) = urn { self.hover(u) } else if let Some(u) = &self.trace { - self.hover(u.clone().as_ref()) + self.hover(&u.clone()) } else { self.arrow(0) } diff --git a/yazi-fs/src/filter.rs b/yazi-fs/src/filter.rs index 71acc30b..e782026a 100644 --- a/yazi-fs/src/filter.rs +++ b/yazi-fs/src/filter.rs @@ -2,7 +2,7 @@ use std::{ffi::OsStr, fmt::Display, ops::Range}; use anyhow::Result; use regex::bytes::{Regex, RegexBuilder}; -use yazi_shared::event::Cmd; +use yazi_shared::{event::Cmd, url::Urn}; pub struct Filter { raw: String, @@ -23,9 +23,8 @@ impl Filter { } #[inline] - pub fn matches(&self, name: impl AsRef) -> bool { - self.regex.is_match(name.as_ref().as_encoded_bytes()) - } + #[allow(private_bounds)] + pub fn matches(&self, name: impl Needle) -> bool { self.regex.is_match(name.needle()) } #[inline] pub fn highlighted(&self, name: impl AsRef) -> Option>> { @@ -58,3 +57,16 @@ impl From<&Cmd> for FilterCase { } } } + +// --- Needle +trait Needle { + fn needle(&self) -> &[u8]; +} + +impl Needle for &OsStr { + fn needle(&self) -> &[u8] { self.as_encoded_bytes() } +} + +impl Needle for &Urn { + fn needle(&self) -> &[u8] { self.encoded_bytes() } +} diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index cd17b74c..08f23f36 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -1,6 +1,6 @@ #![allow(clippy::option_map_unit_fn)] -yazi_macro::mod_pub!(data errors event loc pool scheme shell translit url); +yazi_macro::mod_pub!(data errors event loc path pool scheme shell translit url); yazi_macro::mod_flat!(alias bytes chars condition debounce either env id layer natsort os osstr rand ro_cell source string sync_cell terminal tests throttle time utf8); diff --git a/yazi-shared/src/loc/buf.rs b/yazi-shared/src/loc/buf.rs index bcaa7621..bc14fbde 100644 --- a/yazi-shared/src/loc/buf.rs +++ b/yazi-shared/src/loc/buf.rs @@ -1,44 +1,69 @@ -use std::{cmp, ffi::{OsStr, OsString}, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, mem, ops::Deref, path::{Path, PathBuf}}; +use std::{cmp, ffi::OsStr, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, ops::Deref, path::PathBuf}; use anyhow::Result; -use crate::{loc::Loc, url::{Uri, Urn}}; +use crate::{loc::Loc, path::{PathBufLike, PathLike}, url::{Uri, Urn}}; #[derive(Clone, Default, Eq)] -pub struct LocBuf { - pub(super) inner: PathBuf, +pub struct LocBuf { + pub(super) inner: P, pub(super) uri: usize, pub(super) urn: usize, } -impl Deref for LocBuf { - type Target = PathBuf; +impl

Deref for LocBuf

+where + P: PathBufLike, +{ + type Target = P; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef for LocBuf { - fn as_ref(&self) -> &Path { &self.inner } +impl

AsRef for LocBuf

+where + P: PathBufLike, +{ + fn as_ref(&self) -> &P::Borrowed { self.inner.as_ref() } } -impl PartialEq for LocBuf { +impl

PartialEq for LocBuf

+where + P: PathBufLike + PartialEq, +{ fn eq(&self, other: &Self) -> bool { self.inner == other.inner } } -impl Ord for LocBuf { +impl

Ord for LocBuf

+where + P: PathBufLike + Ord, +{ fn cmp(&self, other: &Self) -> cmp::Ordering { self.inner.cmp(&other.inner) } } -impl PartialOrd for LocBuf { - fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } +impl

PartialOrd for LocBuf

+where + P: PathBufLike + PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + self.inner.partial_cmp(&other.inner) + } } // --- Hash -impl Hash for LocBuf { +impl

Hash for LocBuf

+where + P: PathBufLike, + P::Borrowed: Hash, +{ fn hash(&self, state: &mut H) { self.as_loc().hash(state) } } -impl Debug for LocBuf { +impl

Debug for LocBuf

+where + P: PathBufLike + Debug, + P::Borrowed: Debug, +{ fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.debug_struct("LocBuf") .field("path", &self.inner) @@ -48,39 +73,47 @@ impl Debug for LocBuf { } } -impl From for LocBuf { - fn from(path: PathBuf) -> Self { - let Loc { inner, uri, urn } = Loc::from(path.as_path()); - let len = inner.as_os_str().len(); +impl

From

for LocBuf

+where + P: PathBufLike, +{ + fn from(path: P) -> Self { + let Loc { inner, uri, urn } = Loc::from(&path); + let len = inner.len(); - let mut bytes = path.into_os_string().into_encoded_bytes(); + let mut bytes = path.into_encoded_bytes(); bytes.truncate(len); - Self { - inner: PathBuf::from(unsafe { OsString::from_encoded_bytes_unchecked(bytes) }), - uri, - urn, - } + Self { inner: unsafe { P::from_encoded_bytes(bytes) }, uri, urn } } } -impl> From<&T> for LocBuf { +impl> From<&T> for LocBuf { fn from(value: &T) -> Self { Self::from(PathBuf::from(value)) } } -impl LocBuf { - pub fn new(path: impl Into, base: &Path, trail: &Path) -> Self { - let loc = Self::from(path.into()); +impl

LocBuf

+where + P: PathBufLike, +{ + pub fn new(path: P, base: &T, trail: &T) -> Self + where + T: AsRef + ?Sized, + { + let loc = Self::from(path); let Loc { inner, uri, urn } = Loc::new(&loc.inner, base, trail); - debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); Self { inner: loc.inner, uri, urn } } - pub fn with(path: PathBuf, uri: usize, urn: usize) -> Result { + pub fn with(path: P, uri: usize, urn: usize) -> Result + where + P::Borrowed: PathLike, + { let loc = Self::from(path); let Loc { inner, uri, urn } = Loc::with(&loc.inner, uri, urn)?; - debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); Ok(Self { inner: loc.inner, uri, urn }) } @@ -88,36 +121,53 @@ impl LocBuf { // pub const fn empty() -> Self { Self { inner: PathBuf::new(), uri: 0, urn: 0 } // } - pub fn zeroed(path: impl Into) -> Self { + pub fn zeroed(path: T) -> Self + where + T: Into

, + { let loc = Self::from(path.into()); let Loc { inner, uri, urn } = Loc::zeroed(&loc.inner); - debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); Self { inner: loc.inner, uri, urn } } - pub fn floated(path: impl Into, base: &Path) -> Self { + pub fn floated(path: T, base: &U) -> Self + where + T: Into

, + U: AsRef + ?Sized, + { let loc = Self::from(path.into()); let Loc { inner, uri, urn } = Loc::floated(&loc.inner, base); - debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); Self { inner: loc.inner, uri, urn } } #[inline] - pub fn as_loc<'a>(&'a self) -> Loc<'a> { Loc::from(self) } + pub fn as_loc<'a>(&'a self) -> Loc<'a, P::Borrowed> { + Loc { inner: self.inner.as_ref(), uri: self.uri, urn: self.urn } + } #[inline] - pub fn to_path(&self) -> PathBuf { self.inner.clone() } + pub fn to_path(&self) -> P + where + P: Clone, + { + self.inner.clone() + } #[inline] - pub fn into_path(self) -> PathBuf { self.inner } + pub fn into_path(self) -> P { self.inner } - pub fn set_name(&mut self, name: impl AsRef) { - let old = self.bytes().len(); + pub fn set_name(&mut self, name: T) + where + T: AsRef, + { + let old = self.inner.len(); self.mutate(|path| path.set_file_name(name)); - let new = self.bytes().len(); + let new = self.len(); if new == old { return; } @@ -139,55 +189,63 @@ impl LocBuf { } #[inline] - pub fn rebase(&self, base: &Path) -> Self { + pub fn rebase(&self, base: &P::Borrowed) -> Self + where + ::Owned: Into, + { let mut loc: Self = base.join(self.uri()).into(); (loc.uri, loc.urn) = (self.uri, self.urn); loc } #[inline] - fn bytes(&self) -> &[u8] { self.inner.as_os_str().as_encoded_bytes() } - - #[inline] - fn mutate(&mut self, f: F) { - let mut inner = mem::take(&mut self.inner); + fn mutate(&mut self, f: F) + where + P: Default, + { + let mut inner = std::mem::take(&mut self.inner); f(&mut inner); self.inner = Self::from(inner).inner; } } // FIXME: macro -impl LocBuf { +impl

LocBuf

+where + P: PathBufLike, +{ #[inline] - pub fn uri(&self) -> &Uri { self.as_loc().uri() } + pub fn uri(&self) -> &Uri { self.as_loc().uri() } #[inline] - pub fn urn(&self) -> &Urn { self.as_loc().urn() } + pub fn urn(&self) -> &Urn { self.as_loc().urn() } #[inline] - pub fn base(&self) -> &Urn { self.as_loc().base() } + pub fn base(&self) -> &Urn { self.as_loc().base() } #[inline] pub fn has_base(&self) -> bool { self.as_loc().has_base() } #[inline] - pub fn trail(&self) -> &Urn { self.as_loc().trail() } + pub fn trail(&self) -> &Urn { self.as_loc().trail() } #[inline] pub fn has_trail(&self) -> bool { self.as_loc().has_trail() } #[inline] - pub fn name(&self) -> Option<&OsStr> { self.as_loc().name() } + pub fn name(&self) -> Option<&::Inner> { self.as_loc().name() } #[inline] - pub fn stem(&self) -> Option<&OsStr> { self.as_loc().stem() } + pub fn stem(&self) -> Option<&::Inner> { self.as_loc().stem() } #[inline] - pub fn ext(&self) -> Option<&OsStr> { self.as_loc().ext() } + pub fn ext(&self) -> Option<&::Inner> { self.as_loc().ext() } } #[cfg(test)] mod tests { + use std::path::Path; + use super::*; use crate::url::{UrlBuf, UrlLike}; @@ -217,42 +275,42 @@ mod tests { #[test] fn test_with() -> Result<()> { - let loc = LocBuf::with("/".into(), 0, 0)?; + let loc = LocBuf::::with("/".into(), 0, 0)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("")); assert_eq!(loc.urn().as_os_str(), OsStr::new("")); assert_eq!(loc.name(), None); assert_eq!(loc.base().as_os_str(), OsStr::new("/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/")); - let loc = LocBuf::with("/root/code/".into(), 1, 1)?; + let loc = LocBuf::::with("/root/code/".into(), 1, 1)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code")); assert_eq!(loc.urn().as_os_str(), OsStr::new("code")); assert_eq!(loc.name().unwrap(), OsStr::new("code")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/")); - let loc = LocBuf::with("/root/code/foo//".into(), 2, 1)?; + let loc = LocBuf::::with("/root/code/foo//".into(), 2, 1)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo")); assert_eq!(loc.name().unwrap(), OsStr::new("foo")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/code/")); - let loc = LocBuf::with("/root/code/foo//".into(), 2, 2)?; + let loc = LocBuf::::with("/root/code/foo//".into(), 2, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.urn().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.name().unwrap(), OsStr::new("foo")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/")); - let loc = LocBuf::with("/root/code/foo//bar/".into(), 2, 2)?; + let loc = LocBuf::::with("/root/code/foo//bar/".into(), 2, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.name().unwrap(), OsStr::new("bar")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/code/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/code/")); - let loc = LocBuf::with("/root/code/foo//bar/".into(), 3, 2)?; + let loc = LocBuf::::with("/root/code/foo//bar/".into(), 3, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo//bar")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.name().unwrap(), OsStr::new("bar")); diff --git a/yazi-shared/src/loc/loc.rs b/yazi-shared/src/loc/loc.rs index 9fbd51b1..11b91992 100644 --- a/yazi-shared/src/loc/loc.rs +++ b/yazi-shared/src/loc/loc.rs @@ -1,95 +1,120 @@ -use std::{ffi::OsStr, hash::{Hash, Hasher}, ops::Deref, path::Path}; +use std::{hash::{Hash, Hasher}, ops::Deref, path::Path}; use anyhow::{Result, bail}; -use crate::{loc::LocBuf, url::{Uri, Urn}}; +use crate::{loc::LocBuf, path::{PathInner, PathLike}, url::{Uri, Urn}}; -#[derive(Clone, Copy, Debug)] -pub struct Loc<'a> { - pub(super) inner: &'a Path, +#[derive(Debug)] +pub struct Loc<'a, P: ?Sized + PathLike = Path> { + pub(super) inner: &'a P, pub(super) uri: usize, pub(super) urn: usize, } -impl Default for Loc<'_> { - fn default() -> Self { Self { inner: Path::new(""), uri: 0, urn: 0 } } +impl<'a, P> Copy for Loc<'a, P> where P: ?Sized + PathLike {} + +impl<'a, P> Clone for Loc<'a, P> +where + P: ?Sized + PathLike, +{ + fn clone(&self) -> Self { *self } } -impl Deref for Loc<'_> { - type Target = Path; +impl

Default for Loc<'static, P> +where + P: ?Sized + PathLike, +{ + fn default() -> Self { Self { inner: P::default(), uri: 0, urn: 0 } } +} + +impl

Deref for Loc<'_, P> +where + P: ?Sized + PathLike, +{ + type Target = P; fn deref(&self) -> &Self::Target { self.inner } } -impl AsRef for Loc<'_> { - fn as_ref(&self) -> &Path { self.inner } -} - -impl<'a> From<&'a LocBuf> for Loc<'a> { - fn from(value: &'a LocBuf) -> Self { - Self { inner: &value.inner, uri: value.uri, urn: value.urn } - } +impl

AsRef

for Loc<'_, P> +where + P: ?Sized + PathLike, +{ + fn as_ref(&self) -> &P { self.inner } } // --- Hash -impl Hash for Loc<'_> { +impl

Hash for Loc<'_, P> +where + P: ?Sized + PathLike + Hash, +{ fn hash(&self, state: &mut H) { self.inner.hash(state) } } -impl<'a, T: ?Sized + AsRef> From<&'a T> for Loc<'a> { +impl<'a, P, T> From<&'a T> for Loc<'a, P> +where + P: ?Sized + PathLike, + T: ?Sized + AsRef

, +{ fn from(value: &'a T) -> Self { - let path = Path::new(value.as_ref()); + let path = value.as_ref(); let Some(name) = path.file_name() else { - let uri = path.as_os_str().len(); + let uri = path.len(); return Self { inner: path, uri, urn: 0 }; }; let name_len = name.len(); - let prefix_len = unsafe { - name - .as_encoded_bytes() - .as_ptr() - .offset_from_unsigned(path.as_os_str().as_encoded_bytes().as_ptr()) - }; + let prefix_len = + unsafe { name.encoded_bytes().as_ptr().offset_from_unsigned(path.encoded_bytes().as_ptr()) }; - let bytes = path.as_os_str().as_encoded_bytes(); + let bytes = path.encoded_bytes(); Self { - inner: Path::new(unsafe { - OsStr::from_encoded_bytes_unchecked(&bytes[..prefix_len + name_len]) - }), + inner: unsafe { P::from_encoded_bytes(&bytes[..prefix_len + name_len]) }, uri: name_len, urn: name_len, } } } -impl From> for LocBuf { - fn from(value: Loc<'_>) -> Self { +impl

From> for LocBuf<

::Owned> +where + P: ?Sized + PathLike + ToOwned::Owned>, +{ + fn from(value: Loc<'_, P>) -> Self { Self { inner: value.inner.to_owned(), uri: value.uri, urn: value.urn } } } // --- Eq -impl PartialEq for Loc<'_> { +impl

PartialEq for Loc<'_, P> +where + P: ?Sized + PathLike + PartialEq, +{ fn eq(&self, other: &Self) -> bool { self.inner == other.inner } } -impl Eq for Loc<'_> {} +impl

Eq for Loc<'_, P> where P: ?Sized + PathLike + Eq {} -impl<'a> Loc<'a> { - pub fn new(path: &'a T, base: &Path, trail: &Path) -> Self +impl<'a, P> Loc<'a, P> +where + P: ?Sized + PathLike, +{ + pub fn new(path: &'a T, base: &U, trail: &U) -> Self where - T: AsRef + ?Sized, + T: AsRef

+ ?Sized, + U: AsRef

+ ?Sized, { - let mut loc = Self::from(path.as_ref()); - loc.uri = - loc.inner.strip_prefix(base).expect("Loc must start with the given base").as_os_str().len(); - loc.urn = - loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").as_os_str().len(); + let mut loc = Self::from(path); + loc.uri = loc.inner.strip_prefix(base).expect("Loc must start with the given base").len(); + loc.urn = loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").len(); loc } - pub fn with(path: &'a Path, uri: usize, urn: usize) -> Result { + pub fn with(path: &'a T, uri: usize, urn: usize) -> Result + where + T: ?Sized + AsRef

, +

::Components<'a>: AsRef

+ Clone + DoubleEndedIterator, + { if urn > uri { bail!("URN cannot be longer than URI"); } @@ -108,26 +133,32 @@ impl<'a> Loc<'a> { bail!("URI exceeds the entire URL"); } if i == urn { - loc.urn = loc.strip_prefix(it.clone()).unwrap().as_os_str().len(); + loc.urn = loc.strip_prefix(it.clone()).unwrap().len(); } if i == uri { - loc.uri = loc.strip_prefix(it).unwrap().as_os_str().len(); + loc.uri = loc.strip_prefix(it).unwrap().len(); break; } } Ok(loc) } - pub fn zeroed + ?Sized>(path: &'a T) -> Self { - let mut loc = Self::from(path.as_ref()); + pub fn zeroed(path: &'a T) -> Self + where + T: AsRef

+ ?Sized, + { + let mut loc = Self::from(path); (loc.uri, loc.urn) = (0, 0); loc } - pub fn floated + ?Sized>(path: &'a T, base: &Path) -> Self { - let mut loc = Self::from(path.as_ref()); - loc.uri = - loc.inner.strip_prefix(base).expect("Loc must start with the given base").as_os_str().len(); + pub fn floated(path: &'a T, base: &U) -> Self + where + T: AsRef

+ ?Sized, + U: AsRef

+ ?Sized, + { + let mut loc = Self::from(path); + loc.uri = loc.inner.strip_prefix(base).expect("Loc must start with the given base").len(); loc } @@ -135,65 +166,57 @@ impl<'a> Loc<'a> { pub fn as_loc(self) -> Self { self } #[inline] - pub fn as_path(self) -> &'a Path { self.inner } + pub fn as_path(self) -> &'a P { self.inner } #[inline] - pub fn uri(self) -> &'a Uri { + pub fn uri(self) -> &'a Uri

{ Uri::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(self.bytes().len() - self.uri..), - ) + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.uri..)) }) } #[inline] - pub fn urn(self) -> &'a Urn { + pub fn urn(self) -> &'a Urn

{ Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(self.bytes().len() - self.urn..), - ) + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.urn..)) }) } #[inline] - pub fn base(self) -> &'a Urn { + pub fn base(self) -> &'a Urn

{ Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(..self.bytes().len() - self.uri), - ) + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.uri)) }) } #[inline] - pub fn has_base(self) -> bool { self.bytes().len() != self.uri } + pub fn has_base(self) -> bool { self.inner.len() != self.uri } #[inline] - pub fn trail(self) -> &'a Urn { + pub fn trail(self) -> &'a Urn

{ Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(..self.bytes().len() - self.urn), - ) + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.urn)) }) } #[inline] - pub fn has_trail(self) -> bool { self.bytes().len() != self.urn } + pub fn has_trail(self) -> bool { self.inner.len() != self.urn } #[inline] - pub fn name(self) -> Option<&'a OsStr> { self.inner.file_name() } + pub fn name(self) -> Option<&'a P::Inner> { self.inner.file_name() } #[inline] - pub fn stem(self) -> Option<&'a OsStr> { self.inner.file_stem() } + pub fn stem(self) -> Option<&'a P::Inner> { self.inner.file_stem() } #[inline] - pub fn ext(self) -> Option<&'a OsStr> { self.inner.extension() } + pub fn ext(self) -> Option<&'a P::Inner> { self.inner.extension() } #[inline] - pub fn parent(self) -> Option<&'a Path> { self.inner.parent() } + pub fn parent(self) -> Option<&'a P> { self.inner.parent() } #[inline] - pub fn triple(self) -> (&'a Path, &'a Path, &'a Path) { - let len = self.bytes().len(); + pub fn triple(self) -> (&'a P, &'a P, &'a P) { + let len = self.inner.len(); let base = ..len - self.uri; let rest = len - self.uri..len - self.urn; @@ -201,18 +224,18 @@ impl<'a> Loc<'a> { unsafe { ( - Path::new(OsStr::from_encoded_bytes_unchecked(self.bytes().get_unchecked(base))), - Path::new(OsStr::from_encoded_bytes_unchecked(self.bytes().get_unchecked(rest))), - Path::new(OsStr::from_encoded_bytes_unchecked(self.bytes().get_unchecked(urn))), + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(base)), + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(rest)), + P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(urn)), ) } } #[inline] - pub fn strip_prefix(self, base: impl AsRef) -> Option<&'a Path> { - self.inner.strip_prefix(base).ok() + pub fn strip_prefix(self, base: T) -> Option<&'a P> + where + T: AsRef

, + { + self.inner.strip_prefix(base) } - - #[inline] - pub fn bytes(self) -> &'a [u8] { self.inner.as_os_str().as_encoded_bytes() } } diff --git a/yazi-shared/src/path/mod.rs b/yazi-shared/src/path/mod.rs new file mode 100644 index 00000000..ff9b6f21 --- /dev/null +++ b/yazi-shared/src/path/mod.rs @@ -0,0 +1 @@ +yazi_macro::mod_flat!(traits); diff --git a/yazi-shared/src/path/traits.rs b/yazi-shared/src/path/traits.rs new file mode 100644 index 00000000..3e7dc6c7 --- /dev/null +++ b/yazi-shared/src/path/traits.rs @@ -0,0 +1,122 @@ +use std::{ffi::{OsStr, OsString}, path::{Path, PathBuf}}; + +pub trait PathLike: AsRef { + type Inner: ?Sized + PathInner; + type Owned: PathBufLike + Into; + type Components<'a>: AsRef + Clone + DoubleEndedIterator + where + Self: 'a; + + fn components(&self) -> Self::Components<'_>; + + fn default() -> &'static Self; + + fn encoded_bytes(&self) -> &[u8]; + + fn extension(&self) -> Option<&Self::Inner>; + + fn file_name(&self) -> Option<&Self::Inner>; + + fn file_stem(&self) -> Option<&Self::Inner>; + + unsafe fn from_encoded_bytes(bytes: &[u8]) -> &Self; + + fn join(&self, base: T) -> Self::Owned + where + T: AsRef; + + fn len(&self) -> usize { self.encoded_bytes().len() } + + fn parent(&self) -> Option<&Self>; + + fn strip_prefix(&self, base: T) -> Option<&Self> + where + T: AsRef; +} + +pub trait PathBufLike: AsRef + Default + 'static { + type Inner: AsRef; + type InnerRef: ?Sized + PathInner; + type Borrowed: ?Sized + PathLike + AsRef; + + fn encoded_bytes(&self) -> &[u8]; + + unsafe fn from_encoded_bytes(bytes: Vec) -> Self; + + fn into_encoded_bytes(self) -> Vec; + + fn len(&self) -> usize { self.encoded_bytes().len() } + + fn set_file_name(&mut self, name: T) + where + T: AsRef; +} + +pub trait PathInner { + fn len(&self) -> usize { self.encoded_bytes().len() } + + fn encoded_bytes(&self) -> &[u8]; +} + +impl PathLike for Path { + type Components<'a> = std::path::Components<'a>; + type Inner = OsStr; + type Owned = PathBuf; + + fn components(&self) -> Self::Components<'_> { self.components() } + + fn default() -> &'static Self { Path::new("") } + + fn encoded_bytes(&self) -> &[u8] { self.as_os_str().as_encoded_bytes() } + + fn extension(&self) -> Option<&Self::Inner> { self.extension() } + + fn file_name(&self) -> Option<&Self::Inner> { self.file_name() } + + fn file_stem(&self) -> Option<&Self::Inner> { self.file_stem() } + + unsafe fn from_encoded_bytes(bytes: &[u8]) -> &Self { + Self::new(unsafe { Self::Inner::from_encoded_bytes_unchecked(bytes) }) + } + + fn join(&self, base: T) -> Self::Owned + where + T: AsRef, + { + self.join(base) + } + + fn parent(&self) -> Option<&Self> { self.parent() } + + fn strip_prefix(&self, base: T) -> Option<&Self> + where + T: AsRef, + { + self.strip_prefix(base).ok() + } +} + +impl PathBufLike for PathBuf { + type Borrowed = Path; + type Inner = OsString; + type InnerRef = OsStr; + + fn encoded_bytes(&self) -> &[u8] { self.as_os_str().as_encoded_bytes() } + + unsafe fn from_encoded_bytes(bytes: Vec) -> Self { + Self::from(unsafe { Self::Inner::from_encoded_bytes_unchecked(bytes) }) + } + + fn into_encoded_bytes(self) -> Vec { self.into_os_string().into_encoded_bytes() } + + fn set_file_name(&mut self, name: T) + where + T: AsRef, + { + self.set_file_name(name); + } +} + +impl PathInner for OsStr { + fn encoded_bytes(&self) -> &[u8] { self.as_encoded_bytes() } +} diff --git a/yazi-shared/src/url/uri.rs b/yazi-shared/src/url/uri.rs index 3b6d59a8..91402a9b 100644 --- a/yazi-shared/src/url/uri.rs +++ b/yazi-shared/src/url/uri.rs @@ -1,31 +1,39 @@ -use std::{ops::Deref, path::{Component, Path}}; +use std::{ops::Deref, path::Path}; + +use crate::path::PathLike; #[derive(Debug, Eq, PartialEq, Hash)] #[repr(transparent)] -pub struct Uri(Path); +pub struct Uri(P); -impl Uri { +impl

Uri

+where + P: ?Sized + PathLike, +{ #[inline] - pub fn new + ?Sized>(p: &T) -> &Self { - unsafe { &*(p.as_ref() as *const Path as *const Self) } + pub fn new + ?Sized>(p: &T) -> &Self { + unsafe { &*(p.as_ref() as *const P as *const Self) } } #[inline] pub fn count(&self) -> usize { self.0.components().count() } #[inline] - pub fn nth(&self, n: usize) -> Option> { self.0.components().nth(n) } - - #[inline] - pub fn is_empty(&self) -> bool { self.0.as_os_str().is_empty() } + pub fn is_empty(&self) -> bool { self.0.len() == 0 } } -impl Deref for Uri { - type Target = Path; +impl

Deref for Uri

+where + P: ?Sized + PathLike, +{ + type Target = P; fn deref(&self) -> &Self::Target { &self.0 } } -impl AsRef for Uri { - fn as_ref(&self) -> &Path { &self.0 } +impl

AsRef

for Uri

+where + P: ?Sized + PathLike, +{ + fn as_ref(&self) -> &P { &self.0 } } diff --git a/yazi-shared/src/url/url.rs b/yazi-shared/src/url/url.rs index aca0d8a6..6dc8f6d9 100644 --- a/yazi-shared/src/url/url.rs +++ b/yazi-shared/src/url/url.rs @@ -161,7 +161,7 @@ impl<'a> Url<'a> { // Archive S::Archive(_) if uri.is_empty() => Self { loc: parent.into(), scheme: S::Regular }, - S::Archive(_) if uri.nth(1).is_none() => { + S::Archive(_) if uri.components().nth(1).is_none() => { Self { loc: Loc::zeroed(parent), scheme: self.scheme } } S::Archive(_) => Self { loc: Loc::floated(parent, self.loc.base()), scheme: self.scheme }, diff --git a/yazi-shared/src/url/urn.rs b/yazi-shared/src/url/urn.rs index ebea5339..fff741f7 100644 --- a/yazi-shared/src/url/urn.rs +++ b/yazi-shared/src/url/urn.rs @@ -1,100 +1,124 @@ -use std::{borrow::{Borrow, Cow}, ffi::OsStr, ops::Deref, path::{Path, PathBuf}}; +use std::{borrow::Borrow, ops::Deref, path::{Path, PathBuf}}; use serde::Serialize; +use crate::path::{PathBufLike, PathLike}; + #[derive(Debug, Eq, PartialEq, Hash)] #[repr(transparent)] -pub struct Urn(Path); +pub struct Urn(P); -impl Urn { +impl

Urn

+where + P: ?Sized + PathLike, +{ #[inline] - pub fn new + ?Sized>(p: &T) -> &Self { - unsafe { &*(p.as_ref() as *const Path as *const Self) } + pub fn new + ?Sized>(p: &T) -> &Self { + unsafe { &*(p.as_ref() as *const P as *const Self) } } #[inline] - pub fn name(&self) -> Option<&OsStr> { self.0.file_name() } + pub fn name(&self) -> Option<&P::Inner> { self.0.file_name() } #[inline] pub fn count(&self) -> usize { self.0.components().count() } #[inline] - pub fn encoded_bytes(&self) -> &[u8] { self.0.as_os_str().as_encoded_bytes() } + pub fn encoded_bytes(&self) -> &[u8] { self.0.encoded_bytes() } #[cfg(unix)] #[inline] pub fn is_hidden(&self) -> bool { - use std::os::unix::ffi::OsStrExt; - self.name().is_some_and(|s| s.as_bytes().starts_with(b".")) + use crate::path::PathInner; + self.name().is_some_and(|s| s.encoded_bytes().starts_with(b".")) } } -impl Deref for Urn { - type Target = Path; +impl

Deref for Urn

+where + P: ?Sized + PathLike, +{ + type Target = P; fn deref(&self) -> &Self::Target { &self.0 } } -impl AsRef for Urn { - fn as_ref(&self) -> &Path { &self.0 } +impl

AsRef

for Urn

+where + P: ?Sized + PathLike, +{ + fn as_ref(&self) -> &P { &self.0 } } -impl AsRef for Urn { - fn as_ref(&self) -> &OsStr { self.0.as_os_str() } +impl

From<&Urn

> for PathBuf +where + P: ?Sized + PathLike + ToOwned, +{ + fn from(value: &Urn

) -> Self { value.0.to_owned() } } -impl ToOwned for Urn { - type Owned = UrnBuf; +impl

ToOwned for Urn

+where + P: ?Sized + PathLike + ToOwned::Owned>, + UrnBuf<

::Owned>: Borrow>, +{ + type Owned = UrnBuf<

::Owned>; fn to_owned(&self) -> Self::Owned { UrnBuf(self.0.to_owned()) } } -impl> PartialEq for Urn { - fn eq(&self, other: &T) -> bool { self.0 == other.as_ref() } -} - -impl PartialEq> for &Urn { - fn eq(&self, other: &Cow) -> bool { self.0 == other.as_ref() } +impl

PartialEq> for &Urn

+where + P: ?Sized + PathLike + PartialEq, +{ + fn eq(&self, other: &UrnBuf) -> bool { self.0 == other.0 } } // --- UrnBuf #[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize)] -pub struct UrnBuf(PathBuf); +pub struct UrnBuf(P); -impl Deref for UrnBuf { - type Target = Urn; - - fn deref(&self) -> &Self::Target { self.borrow() } +impl

Borrow> for UrnBuf

+where + P: PathBufLike, +{ + fn borrow(&self) -> &Urn { Urn::new(&self.0) } } -impl Borrow for UrnBuf { - fn borrow(&self) -> &Urn { Urn::new(&self.0) } +impl

Deref for UrnBuf

+where + P: PathBufLike, +{ + type Target = Urn; + + fn deref(&self) -> &Self::Target { Urn::new(&self.0) } } -impl AsRef for UrnBuf { - fn as_ref(&self) -> &Urn { self.borrow() } +impl

AsRef for UrnBuf

+where + P: PathBufLike, +{ + fn as_ref(&self) -> &P::Borrowed { Urn::new(&self.0) } } -impl AsRef for UrnBuf { - fn as_ref(&self) -> &Path { &self.0 } +impl

PartialEq> for UrnBuf

+where + P: PathBufLike + PartialEq, +{ + fn eq(&self, other: &Urn) -> bool { self.0 == other.0 } } -impl PartialEq for UrnBuf { - fn eq(&self, other: &Urn) -> bool { self.0 == other.0 } +impl From for UrnBuf +where + T: Into, +{ + fn from(value: T) -> Self { Self(value.into()) } } -impl PartialEq for Urn { - fn eq(&self, other: &UrnBuf) -> bool { self.0 == other.0 } -} - -impl> From for UrnBuf { - fn from(p: T) -> Self { Self(p.into()) } -} - -impl UrnBuf { +impl

UrnBuf

+where + P: PathBufLike, +{ #[inline] - pub fn as_urn(&self) -> &Urn { self.borrow() } - - #[inline] - pub fn as_os_str(&self) -> &OsStr { self.0.as_os_str() } + pub fn as_urn(&self) -> &Urn { self } } diff --git a/yazi-vfs/src/op.rs b/yazi-vfs/src/op.rs index b0fe21d8..32634a6b 100644 --- a/yazi-vfs/src/op.rs +++ b/yazi-vfs/src/op.rs @@ -15,7 +15,7 @@ impl VfsFilesOp for FilesOp { } else if maybe_exists(cwd).await { Self::IOErr(cwd.clone(), err).emit(); } else if let Some((p, n)) = cwd.pair() { - Self::Deleting(p.into(), [n.into()].into()).emit(); + Self::Deleting(p.into(), [n.to_owned()].into()).emit(); } } } diff --git a/yazi-watcher/src/local/local.rs b/yazi-watcher/src/local/local.rs index 2f1de80a..90de2cf2 100644 --- a/yazi-watcher/src/local/local.rs +++ b/yazi-watcher/src/local/local.rs @@ -70,18 +70,18 @@ impl Local { for u in urls { let Some((parent, urn)) = u.pair() else { continue }; let Ok(file) = File::new(&u).await else { - ops.push(FilesOp::Deleting(parent.into(), [urn.into()].into())); + ops.push(FilesOp::Deleting(parent.into(), [urn.to_owned()].into())); continue; }; if let Some(p) = file.url.as_path() && !provider::local::must_case_match(p).await { - ops.push(FilesOp::Deleting(parent.into(), [urn.into()].into())); + ops.push(FilesOp::Deleting(parent.into(), [urn.to_owned()].into())); continue; } - ops.push(FilesOp::Upserting(parent.into(), [(urn.into(), file)].into())); + ops.push(FilesOp::Upserting(parent.into(), [(urn.to_owned(), file)].into())); } FilesOp::mutate(ops); diff --git a/yazi-watcher/src/remote/remote.rs b/yazi-watcher/src/remote/remote.rs index dde45220..cd29029c 100644 --- a/yazi-watcher/src/remote/remote.rs +++ b/yazi-watcher/src/remote/remote.rs @@ -39,14 +39,14 @@ impl Remote { for u in urls { let Some((parent, urn)) = u.pair() else { continue }; let Ok(mut file) = File::new(&u).await else { - ops.push(FilesOp::Deleting(parent.into(), [urn.into()].into())); + ops.push(FilesOp::Deleting(parent.into(), [urn.to_owned()].into())); continue; }; let is_file = file.is_file(); file.cha.ctime = Some(SystemTime::now()); - ops.push(FilesOp::Upserting(parent.into(), [(urn.into(), file)].into())); + ops.push(FilesOp::Upserting(parent.into(), [(urn.to_owned(), file)].into())); if is_file { ups.push(u); }