diff --git a/yazi-shared/src/path/buf.rs b/yazi-shared/src/path/buf.rs index 730c317d..807c65a9 100644 --- a/yazi-shared/src/path/buf.rs +++ b/yazi-shared/src/path/buf.rs @@ -1,8 +1,8 @@ -use std::{ffi::{OsStr, OsString}, hash::{Hash, Hasher}}; +use std::{ffi::OsString, hash::{Hash, Hasher}}; use hashbrown::Equivalent; -use crate::{path::{AsPath, Component, PathDyn, PathDynError, PathKind, SetNameError}, strand::{AsStrand, Strand}, wtf8::{FromWtf8, FromWtf8Vec}}; +use crate::{path::{AsPath, Component, PathDyn, PathDynError, PathKind, SetNameError}, strand::AsStrand, wtf8::FromWtf8Vec}; // --- PathBufDyn #[derive(Clone, Debug, Eq)] @@ -138,14 +138,10 @@ impl PathBufDyn { where T: AsStrand, { - Ok(match (self, name.as_strand()) { - (Self::Os(p), Strand::Os(s)) => p.set_file_name(s), - (Self::Os(p), Strand::Utf8(s)) => p.set_file_name(s), - (Self::Os(p), Strand::Bytes(b)) => { - p.set_file_name(OsStr::from_wtf8(b).map_err(|_| SetNameError::FromWtf8)?) - } - - (Self::Unix(p), s) => p.set_file_name(s.encoded_bytes()), + let s = name.as_strand(); + Ok(match self { + Self::Os(p) => p.set_file_name(s.as_os()?), + Self::Unix(p) => p.set_file_name(s.encoded_bytes()), }) } diff --git a/yazi-shared/src/path/error.rs b/yazi-shared/src/path/error.rs index 772d7250..175ec67a 100644 --- a/yazi-shared/src/path/error.rs +++ b/yazi-shared/src/path/error.rs @@ -5,13 +5,15 @@ use crate::strand::StrandError; // --- EndsWithError #[derive(Debug, Error)] #[error("calling ends_with on paths with different encodings")] -pub struct EndsWithError; +pub enum EndsWithError { + FromStrand(#[from] StrandError), +} // --- JoinError #[derive(Debug, Error)] #[error("calling join on paths with different encodings")] pub enum JoinError { - FromWtf8, + FromStrand(#[from] StrandError), FromPathDyn(#[from] PathDynError), } @@ -47,7 +49,6 @@ impl From for std::io::Error { #[derive(Debug, Error)] #[error("calling set_name on paths with different encodings")] pub enum SetNameError { - FromWtf8, FromStrand(#[from] StrandError), } @@ -79,7 +80,9 @@ impl From for RsplitOnceError { // --- StartsWithError #[derive(Error, Debug)] #[error("calling starts_with on paths with different encodings")] -pub struct StartsWithError; +pub enum StartsWithError { + FromStrand(#[from] StrandError), +} // --- StripPrefixError #[derive(Debug, Error)] @@ -92,6 +95,14 @@ pub enum StripPrefixError { WrongEncoding, } +impl From for StripPrefixError { + fn from(err: StrandError) -> Self { + match err { + StrandError::AsOs | StrandError::AsUtf8 => Self::WrongEncoding, + } + } +} + impl From for StripPrefixError { fn from(_: std::path::StripPrefixError) -> Self { Self::NotPrefix } } diff --git a/yazi-shared/src/path/path.rs b/yazi-shared/src/path/path.rs index dfdacbab..01c3cca6 100644 --- a/yazi-shared/src/path/path.rs +++ b/yazi-shared/src/path/path.rs @@ -4,7 +4,7 @@ use anyhow::Result; use hashbrown::Equivalent; use super::{RsplitOnceError, StartsWithError}; -use crate::{BytesExt, Utf8BytePredictor, path::{AsPath, Components, Display, EndsWithError, JoinError, PathBufDyn, PathDynError, PathKind, StripPrefixError}, strand::{AsStrand, Strand, StrandError}, wtf8::FromWtf8}; +use crate::{BytesExt, Utf8BytePredictor, path::{AsPath, Components, Display, EndsWithError, JoinError, PathBufDyn, PathDynError, PathKind, StripPrefixError}, strand::{AsStrand, Strand, StrandError}}; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] pub enum PathDyn<'p> { @@ -186,14 +186,10 @@ impl<'p> PathDyn<'p> { where T: AsStrand, { - Ok(match (self, child.as_strand()) { - (Self::Os(p), Strand::Os(q)) => p.ends_with(q), - (Self::Os(p), Strand::Utf8(q)) => p.ends_with(q), - (Self::Os(p), Strand::Bytes(b)) => { - p.ends_with(OsStr::from_wtf8(b).map_err(|_| EndsWithError)?) - } - - (Self::Unix(p), s) => p.ends_with(s.encoded_bytes()), + let s = child.as_strand(); + Ok(match self { + Self::Os(p) => p.ends_with(s.as_os()?), + Self::Unix(p) => p.ends_with(s.encoded_bytes()), }) } @@ -201,14 +197,10 @@ impl<'p> PathDyn<'p> { where T: AsStrand, { - Ok(match (self, path.as_strand()) { - (Self::Os(p), Strand::Os(q)) => PathBufDyn::Os(p.join(q)), - (Self::Os(p), Strand::Utf8(q)) => PathBufDyn::Os(p.join(q)), - (Self::Os(p), Strand::Bytes(b)) => { - PathBufDyn::Os(p.join(OsStr::from_wtf8(b).map_err(|_| JoinError::FromWtf8)?)) - } - - (Self::Unix(p), s) => PathBufDyn::Unix(p.join(s.encoded_bytes())), + let s = path.as_strand(); + Ok(match self { + Self::Os(p) => PathBufDyn::Os(p.join(s.as_os()?)), + Self::Unix(p) => PathBufDyn::Unix(p.join(s.encoded_bytes())), }) } @@ -235,14 +227,10 @@ impl<'p> PathDyn<'p> { where T: AsStrand, { - Ok(match (self, base.as_strand()) { - (Self::Os(p), Strand::Os(s)) => p.starts_with(s), - (Self::Os(p), Strand::Utf8(s)) => p.starts_with(s), - (Self::Os(p), Strand::Bytes(b)) => { - p.starts_with(OsStr::from_wtf8(b).map_err(|_| StartsWithError)?) - } - - (Self::Unix(p), s) => p.starts_with(s.encoded_bytes()), + let s = base.as_strand(); + Ok(match self { + Self::Os(p) => p.starts_with(s.as_os()?), + Self::Unix(p) => p.starts_with(s.encoded_bytes()), }) } @@ -250,14 +238,10 @@ impl<'p> PathDyn<'p> { where T: AsStrand, { - Ok(match (self, base.as_strand()) { - (Self::Os(p), Strand::Os(s)) => Self::Os(p.strip_prefix(s)?), - (Self::Os(p), Strand::Utf8(s)) => Self::Os(p.strip_prefix(s)?), - (Self::Os(p), Strand::Bytes(b)) => { - Self::Os(p.strip_prefix(OsStr::from_wtf8(b).map_err(|_| StripPrefixError::WrongEncoding)?)?) - } - - (Self::Unix(p), s) => Self::Unix(p.strip_prefix(s.encoded_bytes())?), + let s = base.as_strand(); + Ok(match self { + Self::Os(p) => Self::Os(p.strip_prefix(s.as_os()?)?), + Self::Unix(p) => Self::Unix(p.strip_prefix(s.encoded_bytes())?), }) } diff --git a/yazi-shared/src/strand/conversion.rs b/yazi-shared/src/strand/conversion.rs index 2ccdcf18..846f139c 100644 --- a/yazi-shared/src/strand/conversion.rs +++ b/yazi-shared/src/strand/conversion.rs @@ -59,6 +59,10 @@ impl AsStrand for crate::path::Components<'_> { fn as_strand(&self) -> Strand<'_> { self.strand() } } +impl AsStrand for Cow<'_, [u8]> { + fn as_strand(&self) -> Strand<'_> { Strand::Bytes(self) } +} + impl AsStrand for Cow<'_, OsStr> { fn as_strand(&self) -> Strand<'_> { Strand::Os(self) } } diff --git a/yazi-watcher/src/reporter.rs b/yazi-watcher/src/reporter.rs index 50ccc535..abda3763 100644 --- a/yazi-watcher/src/reporter.rs +++ b/yazi-watcher/src/reporter.rs @@ -1,3 +1,6 @@ +use std::borrow::Cow; + +use percent_encoding::percent_decode; use tokio::sync::mpsc; use yazi_shared::{scheme::SchemeKind, url::{AsUrl, Url, UrlBuf, UrlCow, UrlLike}}; @@ -44,7 +47,8 @@ impl Reporter { // Virtual caches let Some(dir) = watched.find_by_cache(parent.loc()) else { continue }; - if let Some(Ok(u)) = url.name().map(|n| dir.try_join(n)) { + let Some(name) = url.name() else { continue }; + if let Ok(u) = dir.try_join(Cow::from(percent_decode(name.encoded_bytes()))) { self.remote_tx.send(u).ok(); } self.remote_tx.send(dir).ok();