fix: make file counter more distinguishable in dark mode (#3311)

This commit is contained in:
三咲雅 misaki masa 2025-11-05 01:20:56 +08:00 committed by GitHub
parent 604b86612a
commit 97c63e2708
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 378 additions and 322 deletions

21
Cargo.lock generated
View file

@ -459,9 +459,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.43" version = "1.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@ -568,9 +568,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_complete_nushell" name = "clap_complete_nushell"
version = "4.5.9" version = "4.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "811159f339691baacdf7d534df2946b9d217014081099e23d31d887d99521e70" checksum = "685bc86fd34b7467e0532a4f8435ab107960d69a243785ef0275e571b35b641a"
dependencies = [ dependencies = [
"clap", "clap",
"clap_complete", "clap_complete",
@ -2233,11 +2233,10 @@ dependencies = [
[[package]] [[package]]
name = "num-bigint-dig" name = "num-bigint-dig"
version = "0.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b"
dependencies = [ dependencies = [
"byteorder",
"lazy_static", "lazy_static",
"libm", "libm",
"num-integer", "num-integer",
@ -3774,9 +3773,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.16" version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
@ -4112,9 +4111,9 @@ dependencies = [
[[package]] [[package]]
name = "version-compare" name = "version-compare"
version = "0.2.0" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
[[package]] [[package]]
name = "version_check" name = "version_check"

View file

@ -50,9 +50,15 @@ serde_json = "1.0.145"
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] } syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
tokio = { version = "1.48.0", features = [ "full" ] } tokio = { version = "1.48.0", features = [ "full" ] }
tokio-stream = "0.1.17" tokio-stream = "0.1.17"
tokio-util = "0.7.16" tokio-util = "0.7.17"
toml = { version = "0.9.8" } toml = { version = "0.9.8" }
tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] } tracing = { version = "0.1.41", features = [ "max_level_debug", "release_max_level_debug" ] }
twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] } twox-hash = { version = "2.1.2", default-features = false, features = [ "std", "random", "xxhash3_128" ] }
unicode-width = { version = "0.2.0", default-features = false } unicode-width = { version = "0.2.0", default-features = false }
uzers = "0.12.1" uzers = "0.12.1"
[workspace.lints.clippy]
format_push_string = "warn"
implicit_clone = "warn"
module_inception = "allow"
use_self = "warn"

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks yanked); yazi_macro::mod_flat!(core file files filter finder folder lives mode preference preview ptr selected tab tabs task tasks yanked);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(align area bar border cell clear constraint edge elements gauge layout line list pad pos rect renderable row span table text wrap); yazi_macro::mod_flat!(align area bar border cell clear constraint edge elements gauge layout line list pad pos rect renderable row span table text wrap);

View file

@ -30,5 +30,5 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
clap = { workspace = true } clap = { workspace = true }
clap_complete = "4.5.60" clap_complete = "4.5.60"
clap_complete_fig = "4.5.2" clap_complete_fig = "4.5.2"
clap_complete_nushell = "4.5.9" clap_complete_nushell = "4.5.10"
vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] } vergen-gitcl = { version = "1.0.8", features = [ "build", "rustc" ] }

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(actions clear_cache debug rustc triple version); yazi_macro::mod_flat!(actions clear_cache debug rustc triple version);

View file

@ -43,7 +43,7 @@ anyhow = { workspace = true }
clap = { workspace = true } clap = { workspace = true }
clap_complete = "4.5.60" clap_complete = "4.5.60"
clap_complete_fig = "4.5.2" clap_complete_fig = "4.5.2"
clap_complete_nushell = "4.5.9" clap_complete_nushell = "4.5.10"
serde_json = { workspace = true } serde_json = { workspace = true }
vergen-gitcl = { version = "1.0.8", features = [ "build" ] } vergen-gitcl = { version = "1.0.8", features = [ "build" ] }

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(add delete dependency deploy git hash install package upgrade); yazi_macro::mod_flat!(add delete dependency deploy git hash install package upgrade);
use anyhow::Context; use anyhow::Context;

View file

@ -41,7 +41,7 @@ marker_selected = { fg = "lightyellow", bg = "lightyellow" }
# Count # Count
count_copied = { fg = "white", bg = "green" } count_copied = { fg = "white", bg = "green" }
count_cut = { fg = "white", bg = "red" } count_cut = { fg = "white", bg = "red" }
count_selected = { fg = "white", bg = "yellow" } count_selected = { fg = "black", bg = "yellow" }
# Border # Border
border_symbol = "│" border_symbol = "│"

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which vfs); yazi_macro::mod_pub!(keymap mgr open opener plugin popup preview tasks theme which vfs);
yazi_macro::mod_flat!(color icon layout pattern platform preset priority style yazi); yazi_macro::mod_flat!(color icon layout pattern platform preset priority style yazi);

View file

@ -1,7 +1,6 @@
#![allow( #![allow(
clippy::if_same_then_else, clippy::if_same_then_else,
clippy::len_without_is_empty, clippy::len_without_is_empty,
clippy::module_inception,
clippy::option_map_unit_fn, clippy::option_map_unit_fn,
clippy::unit_arg clippy::unit_arg
)] )]

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!( yazi_macro::mod_flat!(
bulk bye cd custom delete ember hey hi hover load mount r#move rename tab trash yank bulk bye cd custom delete ember hey hi hover load mount r#move rename tab trash yank
); );

View file

@ -1,4 +1,4 @@
#![allow(clippy::if_same_then_else, clippy::module_inception, clippy::unit_arg)] #![allow(clippy::if_same_then_else, clippy::unit_arg)]
#[cfg(all(not(target_os = "macos"), not(target_os = "windows")))] #[cfg(all(not(target_os = "macos"), not(target_os = "windows")))]
#[global_allocator] #[global_allocator]

View file

@ -10,7 +10,8 @@ pub fn clean_url<'a>(url: impl Into<UrlCow<'a>>) -> UrlBuf {
cow.loc().trail().components().count(), cow.loc().trail().components().count(),
); );
let loc = LocBuf::with(path, uri, urn).expect("Failed to create Loc from cleaned path"); let loc =
LocBuf::<PathBuf>::with(path, uri, urn).expect("Failed to create Loc from cleaned path");
UrlBuf { loc, scheme: cow.into_scheme().into() } UrlBuf { loc, scheme: cow.into_scheme().into() }
} }

View file

@ -22,7 +22,7 @@ fn expand_url_impl<'a>(url: Url<'a>) -> UrlCow<'a> {
let uri_count = url.uri().components().count() as isize; let uri_count = url.uri().components().count() as isize;
let urn_count = url.urn().components().count() as isize; let urn_count = url.urn().components().count() as isize;
let loc = LocBuf::with( let loc = LocBuf::<PathBuf>::with(
PathBuf::from_iter([n_base, n_rest, n_urn]), PathBuf::from_iter([n_base, n_rest, n_urn]),
(uri_count + rest_diff + urn_diff) as usize, (uri_count + rest_diff + urn_diff) as usize,
(urn_count + urn_diff) as usize, (urn_count + urn_diff) as usize,
@ -69,7 +69,7 @@ pub fn absolute_url<'a>(url: Url<'a>) -> UrlCow<'a> {
let b = url.loc.as_os_str().as_encoded_bytes(); let b = url.loc.as_os_str().as_encoded_bytes();
if cfg!(windows) && b.len() == 2 && b[1] == b':' && b[0].is_ascii_alphabetic() { if cfg!(windows) && b.len() == 2 && b[1] == b':' && b[0].is_ascii_alphabetic() {
let loc = LocBuf::with( let loc = LocBuf::<PathBuf>::with(
format!(r"{}:\", b[0].to_ascii_uppercase() as char).into(), format!(r"{}:\", b[0].to_ascii_uppercase() as char).into(),
if url.has_base() { 0 } else { 2 }, if url.has_base() { 0 } else { 2 },
if url.has_trail() { 0 } else { 2 }, if url.has_trail() { 0 } else { 2 },
@ -81,7 +81,7 @@ pub fn absolute_url<'a>(url: Url<'a>) -> UrlCow<'a> {
&& home.is_absolute() && home.is_absolute()
{ {
let add = home.components().count() - 1; // Home root ("~") has offset by the absolute root ("/") let add = home.components().count() - 1; // Home root ("~") has offset by the absolute root ("/")
let loc = LocBuf::with( let loc = LocBuf::<PathBuf>::with(
home.join(rest), home.join(rest),
url.uri().components().count() + if url.has_base() { 0 } else { add }, url.uri().components().count() + if url.has_base() { 0 } else { add },
url.urn().components().count() + if url.has_trail() { 0 } else { add }, url.urn().components().count() + if url.has_trail() { 0 } else { add },
@ -90,7 +90,7 @@ pub fn absolute_url<'a>(url: Url<'a>) -> UrlCow<'a> {
UrlBuf { loc, scheme: url.scheme.into() }.into() UrlBuf { loc, scheme: url.scheme.into() }.into()
} else if !url.is_absolute() { } else if !url.is_absolute() {
let cwd = CWD.path(); let cwd = CWD.path();
let loc = LocBuf::with( let loc = LocBuf::<PathBuf>::with(
cwd.join(url.loc), cwd.join(url.loc),
url.uri().components().count(), url.uri().components().count(),
url.urn().components().count(), url.urn().components().count(),

View file

@ -25,7 +25,7 @@ pub(super) fn url_relative_to<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result<Ur
} }
if from.covariant(&to) { if from.covariant(&to) {
return Ok(UrlBuf { loc: LocBuf::zeroed("."), scheme: to.scheme().into() }.into()); return Ok(UrlBuf { loc: LocBuf::<PathBuf>::zeroed("."), scheme: to.scheme().into() }.into());
} }
let (mut f_it, mut t_it) = (from.components(), to.components()); let (mut f_it, mut t_it) = (from.components(), to.components());
@ -47,5 +47,5 @@ pub(super) fn url_relative_to<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result<Ur
let rest = t_head.into_iter().chain(t_it); let rest = t_head.into_iter().chain(t_it);
let buf: PathBuf = dots.chain(rest).collect(); let buf: PathBuf = dots.chain(rest).collect();
Ok(UrlBuf { loc: LocBuf::zeroed(buf), scheme: to.scheme().into() }.into()) Ok(UrlBuf { loc: LocBuf::<PathBuf>::zeroed(buf), scheme: to.scheme().into() }.into())
} }

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(calculator chan image input layer mouse range); yazi_macro::mod_flat!(calculator chan image input layer mouse range);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(fs op); yazi_macro::mod_flat!(fs op);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(entry fetch isolate peek preload seek spot); yazi_macro::mod_flat!(entry fetch isolate peek preload seek spot);

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(chunk loader require); yazi_macro::mod_flat!(chunk loader require);
pub(super) fn init() { LOADER.with(<_>::default); } pub(super) fn init() { LOADER.with(<_>::default); }

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(child command output process status); yazi_macro::mod_flat!(child command output process status);

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
use mlua::{IntoLua, Lua, Value}; use mlua::{IntoLua, Lua, Value};
use yazi_binding::{Composer, ComposerGet, ComposerSet}; use yazi_binding::{Composer, ComposerGet, ComposerSet};

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!( yazi_macro::mod_flat!(
app cache call image json layer log preview process spot sync target text time user utils app cache call image json layer log preview process spot sync target text time user utils
); );

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(file out progress r#in); yazi_macro::mod_flat!(file out progress r#in);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(out plugin progress r#in); yazi_macro::mod_flat!(out plugin progress r#in);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(out prework progress r#in); yazi_macro::mod_flat!(out prework progress r#in);

View file

@ -1,3 +1 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(out process progress r#in shell); yazi_macro::mod_flat!(out process progress r#in shell);

View file

@ -1,5 +1,3 @@
#![allow(clippy::module_inception)]
yazi_macro::mod_flat!(cmd cow event); yazi_macro::mod_flat!(cmd cow event);
pub static NEED_RENDER: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); pub static NEED_RENDER: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);

View file

@ -1,8 +1,8 @@
use std::{cmp, ffi::OsStr, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, ops::Deref, path::PathBuf}; use std::{cmp, ffi::OsStr, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, marker::PhantomData, ops::Deref, path::PathBuf};
use anyhow::Result; use anyhow::Result;
use crate::{loc::Loc, path::{PathBufLike, PathLike}}; use crate::{loc::Loc, path::{AsInnerView, AsPathView, PathBufLike, PathLike}};
#[derive(Clone, Default, Eq)] #[derive(Clone, Default, Eq)]
pub struct LocBuf<P: PathBufLike = PathBuf> { pub struct LocBuf<P: PathBufLike = PathBuf> {
@ -20,11 +20,9 @@ where
fn deref(&self) -> &Self::Target { &self.inner } fn deref(&self) -> &Self::Target { &self.inner }
} }
impl<P> AsRef<P::Borrowed> for LocBuf<P> // FIXME: remove
where impl AsRef<std::path::Path> for LocBuf<PathBuf> {
P: PathBufLike, fn as_ref(&self) -> &std::path::Path { self.inner.as_ref() }
{
fn as_ref(&self) -> &P::Borrowed { self.inner.as_ref() }
} }
impl<P> PartialEq for LocBuf<P> impl<P> PartialEq for LocBuf<P>
@ -54,7 +52,7 @@ where
impl<P> Hash for LocBuf<P> impl<P> Hash for LocBuf<P>
where where
P: PathBufLike, P: PathBufLike,
P::Borrowed: Hash, for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
{ {
fn hash<H: Hasher>(&self, state: &mut H) { self.as_loc().hash(state) } fn hash<H: Hasher>(&self, state: &mut H) { self.as_loc().hash(state) }
} }
@ -62,7 +60,7 @@ where
impl<P> Debug for LocBuf<P> impl<P> Debug for LocBuf<P>
where where
P: PathBufLike + Debug, P: PathBufLike + Debug,
P::Borrowed: Debug, for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
{ {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("LocBuf") f.debug_struct("LocBuf")
@ -76,9 +74,10 @@ where
impl<P> From<P> for LocBuf<P> impl<P> From<P> for LocBuf<P>
where where
P: PathBufLike, P: PathBufLike,
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
{ {
fn from(path: P) -> Self { fn from(path: P) -> Self {
let Loc { inner, uri, urn } = Loc::from(&path); let Loc { inner, uri, urn, _phantom } = Loc::bare(&path);
let len = inner.len(); let len = inner.len();
let mut bytes = path.into_encoded_bytes(); let mut bytes = path.into_encoded_bytes();
@ -94,13 +93,14 @@ impl<T: ?Sized + AsRef<OsStr>> From<&T> for LocBuf<PathBuf> {
impl<P> LocBuf<P> impl<P> LocBuf<P>
where where
P: PathBufLike, P: PathBufLike,
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
{ {
pub fn new<T>(path: P, base: &T, trail: &T) -> Self pub fn new<'a, T>(path: P, base: T, trail: T) -> Self
where where
T: AsRef<P::Borrowed> + ?Sized, T: for<'b> AsPathView<'a, <P::Borrowed<'b> as PathLike<'b>>::View<'a>>,
{ {
let loc = Self::from(path); let loc = Self::from(path);
let Loc { inner, uri, urn } = Loc::new(&loc.inner, base, trail); let Loc { inner, uri, urn, _phantom } = Loc::new(&loc.inner, base, trail);
debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes());
Self { inner: loc.inner, uri, urn } Self { inner: loc.inner, uri, urn }
@ -108,10 +108,10 @@ where
pub fn with(path: P, uri: usize, urn: usize) -> Result<Self> pub fn with(path: P, uri: usize, urn: usize) -> Result<Self>
where where
P::Borrowed: PathLike, for<'a> P::Borrowed<'a>: PathLike<'a>,
{ {
let loc = Self::from(path); let loc = Self::from(path);
let Loc { inner, uri, urn } = Loc::with(&loc.inner, uri, urn)?; let Loc { inner, uri, urn, _phantom } = Loc::with(&loc.inner, uri, urn)?;
debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes());
Ok(Self { inner: loc.inner, uri, urn }) Ok(Self { inner: loc.inner, uri, urn })
@ -126,27 +126,31 @@ where
T: Into<P>, T: Into<P>,
{ {
let loc = Self::from(path.into()); let loc = Self::from(path.into());
let Loc { inner, uri, urn } = Loc::zeroed(&loc.inner); let Loc { inner, uri, urn, _phantom } = Loc::zeroed(&loc.inner);
debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes());
Self { inner: loc.inner, uri, urn } Self { inner: loc.inner, uri, urn }
} }
pub fn floated<T, U>(path: T, base: &U) -> Self pub fn floated<'a, T>(path: P, base: T) -> Self
where where
T: Into<P>, T: for<'b> AsPathView<'a, <P::Borrowed<'b> as PathLike<'b>>::View<'a>>,
U: AsRef<P::Borrowed> + ?Sized,
{ {
let loc = Self::from(path.into()); let loc = Self::from(path);
let Loc { inner, uri, urn } = Loc::floated(&loc.inner, base); let Loc { inner, uri, urn, _phantom } = Loc::floated(&loc.inner, base);
debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes()); debug_assert!(inner.encoded_bytes() == loc.inner.encoded_bytes());
Self { inner: loc.inner, uri, urn } Self { inner: loc.inner, uri, urn }
} }
#[inline] #[inline]
pub fn as_loc<'a>(&'a self) -> Loc<'a, P::Borrowed> { pub fn as_loc<'a>(&'a self) -> Loc<'a, P::Borrowed<'a>> {
Loc { inner: self.inner.as_ref(), uri: self.uri, urn: self.urn } Loc {
inner: self.inner.as_path_view(),
uri: self.uri,
urn: self.urn,
_phantom: PhantomData,
}
} }
#[inline] #[inline]
@ -162,7 +166,7 @@ where
pub fn set_name<T>(&mut self, name: T) pub fn set_name<T>(&mut self, name: T)
where where
T: AsRef<P::InnerRef>, T: for<'a> AsInnerView<'a, P::InnerRef<'a>>,
{ {
let old = self.inner.len(); let old = self.inner.len();
self.mutate(|path| path.set_file_name(name)); self.mutate(|path| path.set_file_name(name));
@ -189,9 +193,10 @@ where
} }
#[inline] #[inline]
pub fn rebase(&self, base: &P::Borrowed) -> Self pub fn rebase<'a, 'b>(&'a self, base: P::Borrowed<'b>) -> Self
where where
<P::Borrowed as PathLike>::Owned: Into<Self>, 'a: 'b,
for<'c> <P::Borrowed<'c> as PathLike<'c>>::Owned: Into<Self>,
{ {
let mut loc: Self = base.join(self.uri()).into(); let mut loc: Self = base.join(self.uri()).into();
(loc.uri, loc.urn) = (self.uri, self.urn); (loc.uri, loc.urn) = (self.uri, self.urn);
@ -213,33 +218,34 @@ where
impl<P> LocBuf<P> impl<P> LocBuf<P>
where where
P: PathBufLike, P: PathBufLike,
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
{ {
#[inline] #[inline]
pub fn uri(&self) -> &P::Borrowed { self.as_loc().uri() } pub fn uri(&self) -> P::Borrowed<'_> { self.as_loc().uri() }
#[inline] #[inline]
pub fn urn(&self) -> &P::Borrowed { self.as_loc().urn() } pub fn urn(&self) -> P::Borrowed<'_> { self.as_loc().urn() }
#[inline] #[inline]
pub fn base(&self) -> &P::Borrowed { self.as_loc().base() } pub fn base(&self) -> P::Borrowed<'_> { self.as_loc().base() }
#[inline] #[inline]
pub fn has_base(&self) -> bool { self.as_loc().has_base() } pub fn has_base(&self) -> bool { self.as_loc().has_base() }
#[inline] #[inline]
pub fn trail(&self) -> &P::Borrowed { self.as_loc().trail() } pub fn trail(&self) -> P::Borrowed<'_> { self.as_loc().trail() }
#[inline] #[inline]
pub fn has_trail(&self) -> bool { self.as_loc().has_trail() } pub fn has_trail(&self) -> bool { self.as_loc().has_trail() }
#[inline] #[inline]
pub fn name(&self) -> Option<&<P::Borrowed as PathLike>::Inner> { self.as_loc().name() } pub fn name(&self) -> Option<<P::Borrowed<'_> as PathLike<'_>>::Inner> { self.as_loc().name() }
#[inline] #[inline]
pub fn stem(&self) -> Option<&<P::Borrowed as PathLike>::Inner> { self.as_loc().stem() } pub fn stem(&self) -> Option<<P::Borrowed<'_> as PathLike<'_>>::Inner> { self.as_loc().stem() }
#[inline] #[inline]
pub fn ext(&self) -> Option<&<P::Borrowed as PathLike>::Inner> { self.as_loc().ext() } pub fn ext(&self) -> Option<<P::Borrowed<'_> as PathLike<'_>>::Inner> { self.as_loc().ext() }
} }
#[cfg(test)] #[cfg(test)]

View file

@ -1,125 +1,90 @@
use std::{hash::{Hash, Hasher}, ops::Deref, path::Path}; use std::{hash::{Hash, Hasher}, marker::PhantomData, ops::Deref, path::Path};
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use crate::{loc::LocBuf, path::{PathInner, PathLike}}; use crate::{loc::LocBuf, path::{AsPathView, PathBufLike, PathInner, PathLike, ToPathOwned}};
#[derive(Debug)] #[derive(Clone, Copy, Debug)]
pub struct Loc<'a, P: ?Sized + PathLike = Path> { pub struct Loc<'p, P = &'p Path> {
pub(super) inner: &'a P, pub(super) inner: P,
pub(super) uri: usize, pub(super) uri: usize,
pub(super) urn: usize, pub(super) urn: usize,
pub(super) _phantom: PhantomData<&'p ()>,
} }
impl<'a, P> Copy for Loc<'a, P> where P: ?Sized + PathLike {} impl<'p, P> Default for Loc<'p, P>
impl<'a, P> Clone for Loc<'a, P>
where where
P: ?Sized + PathLike, P: PathLike<'p>,
{ {
fn clone(&self) -> Self { *self } fn default() -> Self { Self { inner: P::default(), uri: 0, urn: 0, _phantom: PhantomData } }
} }
impl<P> Default for Loc<'static, P> impl<'p, P> Deref for Loc<'p, P>
where where
P: ?Sized + PathLike, P: PathLike<'p>,
{
fn default() -> Self { Self { inner: P::default(), uri: 0, urn: 0 } }
}
impl<P> Deref for Loc<'_, P>
where
P: ?Sized + PathLike,
{ {
type Target = P; type Target = P;
fn deref(&self) -> &Self::Target { self.inner } fn deref(&self) -> &Self::Target { &self.inner }
} }
impl<P> AsRef<P> for Loc<'_, P> // FIXME: remove
where impl AsRef<std::path::Path> for Loc<'_, &std::path::Path> {
P: ?Sized + PathLike, fn as_ref(&self) -> &std::path::Path { self.inner }
{
fn as_ref(&self) -> &P { self.inner }
} }
// --- Hash // --- Hash
impl<P> Hash for Loc<'_, P> impl<'p, P> Hash for Loc<'p, P>
where where
P: ?Sized + PathLike + Hash, P: PathLike<'p> + Hash,
{ {
fn hash<H: Hasher>(&self, state: &mut H) { self.inner.hash(state) } fn hash<H: Hasher>(&self, state: &mut H) { self.inner.hash(state) }
} }
impl<'a, P, T> From<&'a T> for Loc<'a, P> impl<'p, P> From<Loc<'p, P>> for LocBuf<<P as PathLike<'p>>::Owned>
where where
P: ?Sized + PathLike, P: PathLike<'p> + ToPathOwned<<P as PathLike<'p>>::Owned>,
T: ?Sized + AsRef<P>, <P as PathLike<'p>>::Owned: PathBufLike,
{ {
fn from(value: &'a T) -> Self { fn from(value: Loc<'p, P>) -> Self {
let path = value.as_ref(); Self { inner: value.inner.to_path_owned(), uri: value.uri, urn: value.urn }
let Some(name) = path.file_name() else {
let uri = path.len();
return Self { inner: path, uri, urn: 0 };
};
let name_len = name.len();
let prefix_len =
unsafe { name.encoded_bytes().as_ptr().offset_from_unsigned(path.encoded_bytes().as_ptr()) };
let bytes = path.encoded_bytes();
Self {
inner: unsafe { P::from_encoded_bytes(&bytes[..prefix_len + name_len]) },
uri: name_len,
urn: name_len,
}
}
}
impl<P> From<Loc<'_, P>> for LocBuf<<P as PathLike>::Owned>
where
P: ?Sized + PathLike + ToOwned<Owned = <P as PathLike>::Owned>,
{
fn from(value: Loc<'_, P>) -> Self {
Self { inner: value.inner.to_owned(), uri: value.uri, urn: value.urn }
} }
} }
// --- Eq // --- Eq
impl<P> PartialEq for Loc<'_, P> impl<'p, P> PartialEq for Loc<'p, P>
where where
P: ?Sized + PathLike + PartialEq, P: PathLike<'p> + PartialEq,
{ {
fn eq(&self, other: &Self) -> bool { self.inner == other.inner } fn eq(&self, other: &Self) -> bool { self.inner == other.inner }
} }
impl<P> Eq for Loc<'_, P> where P: ?Sized + PathLike + Eq {} impl<'p, P> Eq for Loc<'p, P> where P: PathLike<'p> + Eq {}
impl<'a, P> Loc<'a, P> impl<'p, P> Loc<'p, P>
where where
P: ?Sized + PathLike, P: PathLike<'p>,
{ {
pub fn new<T, U>(path: &'a T, base: &U, trail: &U) -> Self pub fn new<'a, T, U>(path: T, base: U, trail: U) -> Self
where where
T: AsRef<P> + ?Sized, T: AsPathView<'p, P>,
U: AsRef<P> + ?Sized, U: AsPathView<'a, P::View<'a>>,
{ {
let mut loc = Self::from(path); let mut loc = Self::bare(path);
loc.uri = loc.inner.strip_prefix(base).expect("Loc must start with the given base").len(); 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.urn = loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").len();
loc loc
} }
pub fn with<T>(path: &'a T, uri: usize, urn: usize) -> Result<Self> pub fn with<T>(path: T, uri: usize, urn: usize) -> Result<Self>
where where
T: ?Sized + AsRef<P>, T: AsPathView<'p, P>,
<P as PathLike>::Components<'a>: AsRef<P> + Clone + DoubleEndedIterator,
{ {
if urn > uri { if urn > uri {
bail!("URN cannot be longer than URI"); bail!("URN cannot be longer than URI");
} }
let mut loc = Self::from(path); let mut loc = Self::bare(path);
if uri == 0 { if uri == 0 {
(loc.uri, loc.urn) = (0, 0); (loc.uri, loc.urn) = (0, 0);
return Ok(loc); return Ok(loc);
@ -143,21 +108,44 @@ where
Ok(loc) Ok(loc)
} }
pub fn zeroed<T>(path: &'a T) -> Self pub fn bare<T>(path: T) -> Self
where where
T: AsRef<P> + ?Sized, T: AsPathView<'p, P>,
{ {
let mut loc = Self::from(path); let path = path.as_path_view();
let Some(name) = path.file_name() else {
let uri = path.len();
return Self { inner: path, uri, urn: 0, _phantom: PhantomData };
};
let name_len = name.len();
let prefix_len =
unsafe { name.encoded_bytes().as_ptr().offset_from_unsigned(path.encoded_bytes().as_ptr()) };
let bytes = path.encoded_bytes();
Self {
inner: unsafe { P::from_encoded_bytes(&bytes[..prefix_len + name_len]) },
uri: name_len,
urn: name_len,
_phantom: PhantomData,
}
}
pub fn zeroed<T>(path: T) -> Self
where
T: AsPathView<'p, P>,
{
let mut loc = Self::bare(path);
(loc.uri, loc.urn) = (0, 0); (loc.uri, loc.urn) = (0, 0);
loc loc
} }
pub fn floated<T, U>(path: &'a T, base: &U) -> Self pub fn floated<'a, T, U>(path: T, base: U) -> Self
where where
T: AsRef<P> + ?Sized, T: AsPathView<'p, P>,
U: AsRef<P> + ?Sized, U: AsPathView<'a, P::View<'a>>,
{ {
let mut loc = Self::from(path); let mut loc = Self::bare(path);
loc.uri = loc.inner.strip_prefix(base).expect("Loc must start with the given base").len(); loc.uri = loc.inner.strip_prefix(base).expect("Loc must start with the given base").len();
loc loc
} }
@ -166,24 +154,24 @@ where
pub fn as_loc(self) -> Self { self } pub fn as_loc(self) -> Self { self }
#[inline] #[inline]
pub fn as_path(self) -> &'a P { self.inner } pub fn as_path(self) -> P { self.inner }
#[inline] #[inline]
pub fn uri(self) -> &'a P { pub fn uri(self) -> P {
unsafe { unsafe {
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.uri..)) P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.uri..))
} }
} }
#[inline] #[inline]
pub fn urn(self) -> &'a P { pub fn urn(self) -> P {
unsafe { unsafe {
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.urn..)) P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.urn..))
} }
} }
#[inline] #[inline]
pub fn base(self) -> &'a P { pub fn base(self) -> P {
unsafe { unsafe {
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.uri)) P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.uri))
} }
@ -193,7 +181,7 @@ where
pub fn has_base(self) -> bool { self.inner.len() != self.uri } pub fn has_base(self) -> bool { self.inner.len() != self.uri }
#[inline] #[inline]
pub fn trail(self) -> &'a P { pub fn trail(self) -> P {
unsafe { unsafe {
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.urn)) P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(..self.inner.len() - self.urn))
} }
@ -203,19 +191,19 @@ where
pub fn has_trail(self) -> bool { self.inner.len() != self.urn } pub fn has_trail(self) -> bool { self.inner.len() != self.urn }
#[inline] #[inline]
pub fn name(self) -> Option<&'a P::Inner> { self.inner.file_name() } pub fn name(self) -> Option<P::Inner> { self.inner.file_name() }
#[inline] #[inline]
pub fn stem(self) -> Option<&'a P::Inner> { self.inner.file_stem() } pub fn stem(self) -> Option<P::Inner> { self.inner.file_stem() }
#[inline] #[inline]
pub fn ext(self) -> Option<&'a P::Inner> { self.inner.extension() } pub fn ext(self) -> Option<P::Inner> { self.inner.extension() }
#[inline] #[inline]
pub fn parent(self) -> Option<&'a P> { self.inner.parent() } pub fn parent(self) -> Option<P> { self.inner.parent() }
#[inline] #[inline]
pub fn triple(self) -> (&'a P, &'a P, &'a P) { pub fn triple(self) -> (P, P, P) {
let len = self.inner.len(); let len = self.inner.len();
let base = ..len - self.uri; let base = ..len - self.uri;
@ -232,9 +220,9 @@ where
} }
#[inline] #[inline]
pub fn strip_prefix<T>(self, base: T) -> Option<&'a P> pub fn strip_prefix<'a, T>(self, base: T) -> Option<P>
where where
T: AsRef<P>, T: AsPathView<'a, P::View<'a>>,
{ {
self.inner.strip_prefix(base) self.inner.strip_prefix(base)
} }

View file

@ -0,0 +1,45 @@
use std::{fmt::Debug, hash::Hash};
use crate::path::{AsInnerView, AsPathView, PathInner, PathLike};
pub trait PathBufLike
where
Self: Default + 'static,
{
type Inner: for<'a> AsInnerView<'a, Self::InnerRef<'a>>;
type InnerRef<'a>: PathInner<'a>;
type Borrowed<'a>: PathLike<'a> + AsPathView<'a, Self::Borrowed<'a>> + Debug + Hash;
fn encoded_bytes(&self) -> &[u8];
unsafe fn from_encoded_bytes(bytes: Vec<u8>) -> Self;
fn into_encoded_bytes(self) -> Vec<u8>;
fn len(&self) -> usize { self.encoded_bytes().len() }
fn set_file_name<T>(&mut self, name: T)
where
T: for<'a> AsInnerView<'a, Self::InnerRef<'a>>;
}
impl PathBufLike for std::path::PathBuf {
type Borrowed<'a> = &'a std::path::Path;
type Inner = std::ffi::OsString;
type InnerRef<'a> = &'a std::ffi::OsStr;
fn encoded_bytes(&self) -> &[u8] { self.as_os_str().as_encoded_bytes() }
unsafe fn from_encoded_bytes(bytes: Vec<u8>) -> Self {
Self::from(unsafe { Self::Inner::from_encoded_bytes_unchecked(bytes) })
}
fn into_encoded_bytes(self) -> Vec<u8> { self.into_os_string().into_encoded_bytes() }
fn set_file_name<T>(&mut self, name: T)
where
T: for<'a> AsInnerView<'a, Self::InnerRef<'a>>,
{
self.set_file_name(name.as_inner_view());
}
}

View file

View file

View file

@ -0,0 +1,9 @@
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum PathDyn<'p> {
Os(&'p std::path::Path),
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum PathBufDyn {
Os(std::path::PathBuf),
}

View file

@ -0,0 +1,13 @@
pub trait PathInner<'a>: Copy {
fn len(self) -> usize { self.encoded_bytes().len() }
fn encoded_bytes(self) -> &'a [u8];
}
impl<'a> PathInner<'a> for &'a std::ffi::OsStr {
fn encoded_bytes(self) -> &'a [u8] { self.as_encoded_bytes() }
}
impl<'a> PathInner<'a> for &'a [u8] {
fn encoded_bytes(self) -> &'a [u8] { self }
}

View file

@ -1 +1 @@
yazi_macro::mod_flat!(traits); yazi_macro::mod_flat!(buf component components inner path r#dyn traits);

View file

@ -0,0 +1,81 @@
use crate::path::{AsPathView, PathBufLike, PathInner};
pub trait PathLike<'p>
where
Self: Copy + AsPathView<'p, Self::View<'p>>,
{
type Inner: PathInner<'p>;
type Owned: PathBufLike + Into<Self::Owned>;
type View<'a>;
type Components<'a>: AsPathView<'a, Self::View<'a>> + Clone + DoubleEndedIterator;
fn components(self) -> Self::Components<'p>;
fn default() -> Self;
fn encoded_bytes(self) -> &'p [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: &'p [u8]) -> Self;
#[cfg(unix)]
fn is_hidden(self) -> bool {
self.file_name().map_or(false, |n| n.encoded_bytes().get(0) == Some(&b'.'))
}
fn join<'a, T>(self, base: T) -> Self::Owned
where
T: AsPathView<'a, Self::View<'a>>;
fn len(self) -> usize { self.encoded_bytes().len() }
fn parent(self) -> Option<Self>;
fn strip_prefix<'a, T>(self, base: T) -> Option<Self>
where
T: AsPathView<'a, Self::View<'a>>;
}
impl<'p> PathLike<'p> for &'p std::path::Path {
type Components<'a> = std::path::Components<'a>;
type Inner = &'p std::ffi::OsStr;
type Owned = std::path::PathBuf;
type View<'a> = &'a std::path::Path;
fn components(self) -> Self::Components<'p> { self.components() }
fn default() -> Self { std::path::Path::new("") }
fn encoded_bytes(self) -> &'p [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: &'p [u8]) -> Self {
std::path::Path::new(unsafe { std::ffi::OsStr::from_encoded_bytes_unchecked(bytes) })
}
fn join<'a, T>(self, base: T) -> Self::Owned
where
T: AsPathView<'a, Self::View<'a>>,
{
self.join(base.as_path_view())
}
fn parent(self) -> Option<Self> { self.parent() }
fn strip_prefix<'a, T>(self, base: T) -> Option<Self>
where
T: AsPathView<'a, Self::View<'a>>,
{
self.strip_prefix(base.as_path_view()).ok()
}
}

View file

@ -1,147 +1,90 @@
use std::{ffi::{OsStr, OsString}, path::{Path, PathBuf}}; use crate::path::PathLike;
pub trait AsPath { pub trait AsPath {
fn as_path(&self) -> &(impl ?Sized + PathLike); fn as_path(&self) -> impl PathLike<'_>;
} }
pub trait PathLike: AsRef<Self> { impl AsPath for &std::ffi::OsStr {
type Inner: ?Sized + PathInner; fn as_path(&self) -> impl PathLike<'_> { std::path::Path::new(self) }
type Owned: PathBufLike + Into<Self::Owned>;
type Components<'a>: AsRef<Self> + 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;
#[cfg(unix)]
fn is_hidden(&self) -> bool {
self.file_name().map_or(false, |n| n.encoded_bytes().get(0) == Some(&b'.'))
}
fn join<T>(&self, base: T) -> Self::Owned
where
T: AsRef<Self>;
fn len(&self) -> usize { self.encoded_bytes().len() }
fn parent(&self) -> Option<&Self>;
fn strip_prefix<T>(&self, base: T) -> Option<&Self>
where
T: AsRef<Self>;
} }
pub trait PathBufLike: AsRef<Self::Borrowed> + Default + 'static { impl AsPath for &std::path::Path {
type Inner: AsRef<Self::InnerRef>; fn as_path(&self) -> impl PathLike<'_> { *self }
type InnerRef: ?Sized + PathInner;
type Borrowed: ?Sized + PathLike + AsRef<Self::Borrowed>;
fn encoded_bytes(&self) -> &[u8];
unsafe fn from_encoded_bytes(bytes: Vec<u8>) -> Self;
fn into_encoded_bytes(self) -> Vec<u8>;
fn len(&self) -> usize { self.encoded_bytes().len() }
fn set_file_name<T>(&mut self, name: T)
where
T: AsRef<Self::InnerRef>;
} }
pub trait PathInner { impl AsPath for std::path::PathBuf {
fn len(&self) -> usize { self.encoded_bytes().len() } fn as_path(&self) -> impl PathLike<'_> { self.as_path() }
fn encoded_bytes(&self) -> &[u8];
} }
impl AsPath for &OsStr { impl AsPath for &std::path::PathBuf {
fn as_path(&self) -> &(impl ?Sized + PathLike) { Path::new(self) } fn as_path(&self) -> impl PathLike<'_> { (*self).as_path() }
} }
impl AsPath for &Path { // --- AsPathView
fn as_path(&self) -> &(impl ?Sized + PathLike) { *self } pub trait AsPathView<'a, T> {
fn as_path_view(self) -> T;
} }
impl AsPath for PathBuf { impl<'a> AsPathView<'a, &'a std::path::Path> for &'a str {
fn as_path(&self) -> &(impl ?Sized + PathLike) { self.as_path() } fn as_path_view(self) -> &'a std::path::Path { std::path::Path::new(self) }
} }
impl AsPath for &PathBuf { impl<'a> AsPathView<'a, &'a std::path::Path> for &'a std::path::Path {
fn as_path(&self) -> &(impl ?Sized + PathLike) { (*self).as_path() } fn as_path_view(self) -> &'a std::path::Path { self }
} }
impl PathLike for Path { impl<'a> AsPathView<'a, &'a std::path::Path> for &'a std::path::PathBuf {
type Components<'a> = std::path::Components<'a>; fn as_path_view(self) -> &'a std::path::Path { self }
type Inner = OsStr; }
type Owned = PathBuf;
fn components(&self) -> Self::Components<'_> { self.components() } impl<'a> AsPathView<'a, &'a std::path::Path> for std::path::Components<'a> {
fn as_path_view(self) -> &'a std::path::Path { self.as_path() }
}
fn default() -> &'static Self { Path::new("") } impl<'a> AsPathView<'a, super::PathDyn<'a>> for &'a super::PathBufDyn {
fn as_path_view(self) -> super::PathDyn<'a> {
fn encoded_bytes(&self) -> &[u8] { self.as_os_str().as_encoded_bytes() } match self {
super::PathBufDyn::Os(p) => super::PathDyn::Os(p.as_path()),
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<T>(&self, base: T) -> Self::Owned
where
T: AsRef<Self>,
{
self.join(base)
}
fn parent(&self) -> Option<&Self> { self.parent() }
fn strip_prefix<T>(&self, base: T) -> Option<&Self>
where
T: AsRef<Self>,
{
self.strip_prefix(base).ok()
} }
} }
impl PathBufLike for PathBuf { impl<'a> AsPathView<'a, &'a std::path::Path> for crate::loc::Loc<'a, &'a std::path::Path> {
type Borrowed = Path; fn as_path_view(self) -> &'a std::path::Path { *self }
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<u8>) -> Self {
Self::from(unsafe { Self::Inner::from_encoded_bytes_unchecked(bytes) })
}
fn into_encoded_bytes(self) -> Vec<u8> { self.into_os_string().into_encoded_bytes() }
fn set_file_name<T>(&mut self, name: T)
where
T: AsRef<Self::InnerRef>,
{
self.set_file_name(name);
}
} }
impl PathInner for OsStr { // --- ToPathOwned
fn encoded_bytes(&self) -> &[u8] { self.as_encoded_bytes() } pub trait ToPathOwned<T> {
fn to_path_owned(&self) -> T;
}
impl ToPathOwned<std::path::PathBuf> for std::path::Path {
fn to_path_owned(&self) -> std::path::PathBuf { self.to_owned() }
}
impl<T, U> ToPathOwned<U> for &T
where
T: ?Sized + ToPathOwned<U>,
{
fn to_path_owned(&self) -> U { (*self).to_path_owned() }
}
// --- AsInnerView
pub trait AsInnerView<'a, T> {
fn as_inner_view(&'a self) -> T;
}
impl<'a> AsInnerView<'a, &'a std::ffi::OsStr> for std::ffi::OsStr {
fn as_inner_view(&'a self) -> &'a std::ffi::OsStr { self }
}
impl<'a> AsInnerView<'a, &'a std::ffi::OsStr> for std::ffi::OsString {
fn as_inner_view(&'a self) -> &'a std::ffi::OsStr { self }
}
impl<'a, T, U> AsInnerView<'a, U> for &T
where
T: ?Sized + AsInnerView<'a, U>,
{
fn as_inner_view(&'a self) -> U { (*self).as_inner_view() }
} }

View file

@ -95,7 +95,7 @@ impl UrlBuf {
} }
#[inline] #[inline]
pub fn set_name(&mut self, name: impl AsRef<OsStr>) { self.loc.set_name(name); } pub fn set_name(&mut self, name: impl AsRef<OsStr>) { self.loc.set_name(name.as_ref()); }
#[inline] #[inline]
pub fn rebase(&self, base: &Path) -> Self { pub fn rebase(&self, base: &Path) -> Self {
@ -125,14 +125,14 @@ impl UrlBuf {
#[inline] #[inline]
pub fn to_search(&self, domain: impl AsRef<str>) -> Self { pub fn to_search(&self, domain: impl AsRef<str>) -> Self {
Self { Self {
loc: LocBuf::zeroed(self.loc.to_path()), loc: LocBuf::<PathBuf>::zeroed(self.loc.to_path()),
scheme: Scheme::Search(Pool::<str>::intern(domain)), scheme: Scheme::Search(Pool::<str>::intern(domain)),
} }
} }
#[inline] #[inline]
pub fn into_search(mut self, domain: impl AsRef<str>) -> Self { pub fn into_search(mut self, domain: impl AsRef<str>) -> Self {
self.loc = LocBuf::zeroed(self.loc.into_path()); self.loc = LocBuf::<PathBuf>::zeroed(self.loc.into_path());
self.scheme = Scheme::Search(Pool::<str>::intern(domain)); self.scheme = Scheme::Search(Pool::<str>::intern(domain));
self self
} }

View file

@ -49,12 +49,14 @@ impl<'a> TryFrom<&'a [u8]> for UrlCow<'a> {
let (scheme, path, port) = Self::parse(value)?; let (scheme, path, port) = Self::parse(value)?;
Ok(match (path, port) { Ok(match (path, port) {
(Cow::Borrowed(p), None) => Self::Borrowed { loc: Loc::from(p), scheme }, (Cow::Borrowed(p), None) => Self::Borrowed { loc: Loc::bare(p), scheme },
(Cow::Borrowed(p), Some((uri, urn))) => { (Cow::Borrowed(p), Some((uri, urn))) => {
Self::Borrowed { loc: Loc::with(p, uri, urn)?, scheme } Self::Borrowed { loc: Loc::with(p, uri, urn)?, scheme }
} }
(Cow::Owned(p), None) => Self::Owned { loc: LocBuf::from(p), scheme }, (Cow::Owned(p), None) => Self::Owned { loc: LocBuf::from(p), scheme },
(Cow::Owned(p), Some((uri, urn))) => Self::Owned { loc: LocBuf::with(p, uri, urn)?, scheme }, (Cow::Owned(p), Some((uri, urn))) => {
Self::Owned { loc: LocBuf::<PathBuf>::with(p, uri, urn)?, scheme }
}
}) })
} }
} }

View file

@ -1,6 +1,6 @@
use std::{borrow::Cow, ffi::OsStr, path::{Path, PathBuf}}; use std::{borrow::Cow, ffi::OsStr, path::{Path, PathBuf}};
use crate::{scheme::{AsScheme, SchemeRef}, url::{Components, Display, Url, UrlBuf, UrlCow}}; use crate::{loc::Loc, scheme::{AsScheme, SchemeRef}, url::{Components, Display, Url, UrlBuf, UrlCow}};
// --- AsUrl // --- AsUrl
pub trait AsUrl { pub trait AsUrl {
@ -9,7 +9,7 @@ pub trait AsUrl {
impl AsUrl for Path { impl AsUrl for Path {
#[inline] #[inline]
fn as_url(&self) -> Url<'_> { Url { loc: self.into(), scheme: SchemeRef::Regular } } fn as_url(&self) -> Url<'_> { Url { loc: Loc::bare(self), scheme: SchemeRef::Regular } }
} }
impl AsUrl for &Path { impl AsUrl for &Path {

View file

@ -1,4 +1,4 @@
use std::{borrow::Cow, ffi::OsStr, fmt::{Debug, Formatter}, path::Path}; use std::{borrow::Cow, ffi::OsStr, fmt::{Debug, Formatter}, path::{Path, PathBuf}};
use hashbrown::Equivalent; use hashbrown::Equivalent;
@ -34,7 +34,7 @@ impl Debug for Url<'_> {
impl<'a> Url<'a> { impl<'a> Url<'a> {
#[inline] #[inline]
pub fn regular<T: AsRef<Path> + ?Sized>(path: &'a T) -> Self { pub fn regular<T: AsRef<Path> + ?Sized>(path: &'a T) -> Self {
Self { loc: path.as_ref().into(), scheme: SchemeRef::Regular } Self { loc: Loc::bare(path.as_ref()), scheme: SchemeRef::Regular }
} }
#[inline] #[inline]
@ -42,7 +42,7 @@ impl<'a> Url<'a> {
#[inline] #[inline]
pub fn into_regular(self) -> Self { pub fn into_regular(self) -> Self {
Self { loc: self.loc.as_path().into(), scheme: SchemeRef::Regular } Self { loc: Loc::bare(self.loc.as_path()), scheme: SchemeRef::Regular }
} }
#[inline] #[inline]
@ -71,8 +71,8 @@ impl<'a> Url<'a> {
let loc = match self.scheme { let loc = match self.scheme {
S::Regular => join.into(), S::Regular => join.into(),
S::Search(_) => LocBuf::new(join, self.loc.base(), self.loc.base()), S::Search(_) => LocBuf::<PathBuf>::new(join, self.loc.base(), self.loc.base()),
S::Archive(_) => LocBuf::floated(join, self.loc.base()), S::Archive(_) => LocBuf::<PathBuf>::floated(join, self.loc.base()),
S::Sftp(_) => join.into(), S::Sftp(_) => join.into(),
}; };
@ -134,7 +134,7 @@ impl<'a> Url<'a> {
return None; return None;
} }
let loc: Loc = self.loc.base().into(); let loc = Loc::bare(self.loc.base());
Some(match self.scheme { Some(match self.scheme {
S::Regular => Self { loc, scheme: S::Regular }, S::Regular => Self { loc, scheme: S::Regular },
S::Search(_) => Self { loc, scheme: self.scheme }, S::Search(_) => Self { loc, scheme: self.scheme },
@ -151,11 +151,11 @@ impl<'a> Url<'a> {
Some(match self.scheme { Some(match self.scheme {
// Regular // Regular
S::Regular => Self { loc: parent.into(), scheme: S::Regular }, S::Regular => Self { loc: Loc::bare(parent), scheme: S::Regular },
// Search // Search
S::Search(_) if uri.as_os_str().is_empty() => { S::Search(_) if uri.as_os_str().is_empty() => {
Self { loc: parent.into(), scheme: S::Regular } Self { loc: Loc::bare(parent), scheme: S::Regular }
} }
S::Search(_) => { S::Search(_) => {
Self { loc: Loc::new(parent, self.loc.base(), self.loc.base()), scheme: self.scheme } Self { loc: Loc::new(parent, self.loc.base(), self.loc.base()), scheme: self.scheme }
@ -163,7 +163,7 @@ impl<'a> Url<'a> {
// Archive // Archive
S::Archive(_) if uri.as_os_str().is_empty() => { S::Archive(_) if uri.as_os_str().is_empty() => {
Self { loc: parent.into(), scheme: S::Regular } Self { loc: Loc::bare(parent), scheme: S::Regular }
} }
S::Archive(_) if uri.components().nth(1).is_none() => { S::Archive(_) if uri.components().nth(1).is_none() => {
Self { loc: Loc::zeroed(parent), scheme: self.scheme } Self { loc: Loc::zeroed(parent), scheme: self.scheme }
@ -171,7 +171,7 @@ impl<'a> Url<'a> {
S::Archive(_) => Self { loc: Loc::floated(parent, self.loc.base()), scheme: self.scheme }, S::Archive(_) => Self { loc: Loc::floated(parent, self.loc.base()), scheme: self.scheme },
// SFTP // SFTP
S::Sftp(_) => Self { loc: parent.into(), scheme: self.scheme }, S::Sftp(_) => Self { loc: Loc::bare(parent), scheme: self.scheme },
}) })
} }