mirror of
https://github.com/sxyazi/yazi.git
synced 2026-05-13 08:16:40 +00:00
fix: make file counter more distinguishable in dark mode (#3311)
This commit is contained in:
parent
604b86612a
commit
97c63e2708
42 changed files with 378 additions and 322 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
|
@ -459,9 +459,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.43"
|
||||
version = "1.2.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2"
|
||||
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
|
|
@ -568,9 +568,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete_nushell"
|
||||
version = "4.5.9"
|
||||
version = "4.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "811159f339691baacdf7d534df2946b9d217014081099e23d31d887d99521e70"
|
||||
checksum = "685bc86fd34b7467e0532a4f8435ab107960d69a243785ef0275e571b35b641a"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
|
|
@ -2233,11 +2233,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||
checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libm",
|
||||
"num-integer",
|
||||
|
|
@ -3774,9 +3773,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.16"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
|
||||
checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
|
@ -4112,9 +4111,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
||||
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
|
|
|
|||
|
|
@ -50,9 +50,15 @@ serde_json = "1.0.145"
|
|||
syntect = { version = "5.3.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
tokio = { version = "1.48.0", features = [ "full" ] }
|
||||
tokio-stream = "0.1.17"
|
||||
tokio-util = "0.7.16"
|
||||
tokio-util = "0.7.17"
|
||||
toml = { version = "0.9.8" }
|
||||
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" ] }
|
||||
unicode-width = { version = "0.2.0", default-features = false }
|
||||
uzers = "0.12.1"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
format_push_string = "warn"
|
||||
implicit_clone = "warn"
|
||||
module_inception = "allow"
|
||||
use_self = "warn"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -30,5 +30,5 @@ yazi-shared = { path = "../yazi-shared", version = "25.9.15" }
|
|||
clap = { workspace = true }
|
||||
clap_complete = "4.5.60"
|
||||
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" ] }
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(actions clear_cache debug rustc triple version);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ anyhow = { workspace = true }
|
|||
clap = { workspace = true }
|
||||
clap_complete = "4.5.60"
|
||||
clap_complete_fig = "4.5.2"
|
||||
clap_complete_nushell = "4.5.9"
|
||||
clap_complete_nushell = "4.5.10"
|
||||
serde_json = { workspace = true }
|
||||
vergen-gitcl = { version = "1.0.8", features = [ "build" ] }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(add delete dependency deploy git hash install package upgrade);
|
||||
|
||||
use anyhow::Context;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ marker_selected = { fg = "lightyellow", bg = "lightyellow" }
|
|||
# Count
|
||||
count_copied = { fg = "white", bg = "green" }
|
||||
count_cut = { fg = "white", bg = "red" }
|
||||
count_selected = { fg = "white", bg = "yellow" }
|
||||
count_selected = { fg = "black", bg = "yellow" }
|
||||
|
||||
# Border
|
||||
border_symbol = "│"
|
||||
|
|
|
|||
|
|
@ -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_flat!(color icon layout pattern platform preset priority style yazi);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#![allow(
|
||||
clippy::if_same_then_else,
|
||||
clippy::len_without_is_empty,
|
||||
clippy::module_inception,
|
||||
clippy::option_map_unit_fn,
|
||||
clippy::unit_arg
|
||||
)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(
|
||||
bulk bye cd custom delete ember hey hi hover load mount r#move rename tab trash yank
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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")))]
|
||||
#[global_allocator]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ pub fn clean_url<'a>(url: impl Into<UrlCow<'a>>) -> UrlBuf {
|
|||
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() }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ fn expand_url_impl<'a>(url: Url<'a>) -> UrlCow<'a> {
|
|||
let uri_count = url.uri().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]),
|
||||
(uri_count + rest_diff + 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();
|
||||
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(),
|
||||
if url.has_base() { 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()
|
||||
{
|
||||
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),
|
||||
url.uri().components().count() + if url.has_base() { 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()
|
||||
} else if !url.is_absolute() {
|
||||
let cwd = CWD.path();
|
||||
let loc = LocBuf::with(
|
||||
let loc = LocBuf::<PathBuf>::with(
|
||||
cwd.join(url.loc),
|
||||
url.uri().components().count(),
|
||||
url.urn().components().count(),
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub(super) fn url_relative_to<'a>(from: UrlCow<'_>, to: UrlCow<'a>) -> Result<Ur
|
|||
}
|
||||
|
||||
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());
|
||||
|
|
@ -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 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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(calculator chan image input layer mouse range);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(fs op);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(entry fetch isolate peek preload seek spot);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(chunk loader require);
|
||||
|
||||
pub(super) fn init() { LOADER.with(<_>::default); }
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(child command output process status);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
use mlua::{IntoLua, Lua, Value};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(
|
||||
app cache call image json layer log preview process spot sync target text time user utils
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(file out progress r#in);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(out plugin progress r#in);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(out prework progress r#in);
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(out process progress r#in shell);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(clippy::module_inception)]
|
||||
|
||||
yazi_macro::mod_flat!(cmd cow event);
|
||||
|
||||
pub static NEED_RENDER: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
|
|
|
|||
|
|
@ -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 crate::{loc::Loc, path::{PathBufLike, PathLike}};
|
||||
use crate::{loc::Loc, path::{AsInnerView, AsPathView, PathBufLike, PathLike}};
|
||||
|
||||
#[derive(Clone, Default, Eq)]
|
||||
pub struct LocBuf<P: PathBufLike = PathBuf> {
|
||||
|
|
@ -20,11 +20,9 @@ where
|
|||
fn deref(&self) -> &Self::Target { &self.inner }
|
||||
}
|
||||
|
||||
impl<P> AsRef<P::Borrowed> for LocBuf<P>
|
||||
where
|
||||
P: PathBufLike,
|
||||
{
|
||||
fn as_ref(&self) -> &P::Borrowed { self.inner.as_ref() }
|
||||
// FIXME: remove
|
||||
impl AsRef<std::path::Path> for LocBuf<PathBuf> {
|
||||
fn as_ref(&self) -> &std::path::Path { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
impl<P> PartialEq for LocBuf<P>
|
||||
|
|
@ -54,7 +52,7 @@ where
|
|||
impl<P> Hash for LocBuf<P>
|
||||
where
|
||||
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) }
|
||||
}
|
||||
|
|
@ -62,7 +60,7 @@ where
|
|||
impl<P> Debug for LocBuf<P>
|
||||
where
|
||||
P: PathBufLike + Debug,
|
||||
P::Borrowed: Debug,
|
||||
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
f.debug_struct("LocBuf")
|
||||
|
|
@ -76,9 +74,10 @@ where
|
|||
impl<P> From<P> for LocBuf<P>
|
||||
where
|
||||
P: PathBufLike,
|
||||
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
|
||||
{
|
||||
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 mut bytes = path.into_encoded_bytes();
|
||||
|
|
@ -94,13 +93,14 @@ impl<T: ?Sized + AsRef<OsStr>> From<&T> for LocBuf<PathBuf> {
|
|||
impl<P> LocBuf<P>
|
||||
where
|
||||
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
|
||||
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 { 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());
|
||||
Self { inner: loc.inner, uri, urn }
|
||||
|
|
@ -108,10 +108,10 @@ where
|
|||
|
||||
pub fn with(path: P, uri: usize, urn: usize) -> Result<Self>
|
||||
where
|
||||
P::Borrowed: PathLike,
|
||||
for<'a> P::Borrowed<'a>: PathLike<'a>,
|
||||
{
|
||||
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());
|
||||
Ok(Self { inner: loc.inner, uri, urn })
|
||||
|
|
@ -126,27 +126,31 @@ where
|
|||
T: Into<P>,
|
||||
{
|
||||
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());
|
||||
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
|
||||
T: Into<P>,
|
||||
U: AsRef<P::Borrowed> + ?Sized,
|
||||
T: for<'b> AsPathView<'a, <P::Borrowed<'b> as PathLike<'b>>::View<'a>>,
|
||||
{
|
||||
let loc = Self::from(path.into());
|
||||
let Loc { inner, uri, urn } = Loc::floated(&loc.inner, base);
|
||||
let loc = Self::from(path);
|
||||
let Loc { inner, uri, urn, _phantom } = Loc::floated(&loc.inner, base);
|
||||
|
||||
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, P::Borrowed> {
|
||||
Loc { inner: self.inner.as_ref(), uri: self.uri, urn: self.urn }
|
||||
pub fn as_loc<'a>(&'a self) -> Loc<'a, P::Borrowed<'a>> {
|
||||
Loc {
|
||||
inner: self.inner.as_path_view(),
|
||||
uri: self.uri,
|
||||
urn: self.urn,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -162,7 +166,7 @@ where
|
|||
|
||||
pub fn set_name<T>(&mut self, name: T)
|
||||
where
|
||||
T: AsRef<P::InnerRef>,
|
||||
T: for<'a> AsInnerView<'a, P::InnerRef<'a>>,
|
||||
{
|
||||
let old = self.inner.len();
|
||||
self.mutate(|path| path.set_file_name(name));
|
||||
|
|
@ -189,9 +193,10 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rebase(&self, base: &P::Borrowed) -> Self
|
||||
pub fn rebase<'a, 'b>(&'a self, base: P::Borrowed<'b>) -> Self
|
||||
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();
|
||||
(loc.uri, loc.urn) = (self.uri, self.urn);
|
||||
|
|
@ -213,33 +218,34 @@ where
|
|||
impl<P> LocBuf<P>
|
||||
where
|
||||
P: PathBufLike,
|
||||
for<'a> &'a P: AsPathView<'a, P::Borrowed<'a>>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn uri(&self) -> &P::Borrowed { self.as_loc().uri() }
|
||||
pub fn uri(&self) -> P::Borrowed<'_> { self.as_loc().uri() }
|
||||
|
||||
#[inline]
|
||||
pub fn urn(&self) -> &P::Borrowed { self.as_loc().urn() }
|
||||
pub fn urn(&self) -> P::Borrowed<'_> { self.as_loc().urn() }
|
||||
|
||||
#[inline]
|
||||
pub fn base(&self) -> &P::Borrowed { self.as_loc().base() }
|
||||
pub fn base(&self) -> P::Borrowed<'_> { self.as_loc().base() }
|
||||
|
||||
#[inline]
|
||||
pub fn has_base(&self) -> bool { self.as_loc().has_base() }
|
||||
|
||||
#[inline]
|
||||
pub fn trail(&self) -> &P::Borrowed { self.as_loc().trail() }
|
||||
pub fn trail(&self) -> P::Borrowed<'_> { self.as_loc().trail() }
|
||||
|
||||
#[inline]
|
||||
pub fn has_trail(&self) -> bool { self.as_loc().has_trail() }
|
||||
|
||||
#[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]
|
||||
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]
|
||||
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)]
|
||||
|
|
|
|||
|
|
@ -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 crate::{loc::LocBuf, path::{PathInner, PathLike}};
|
||||
use crate::{loc::LocBuf, path::{AsPathView, PathBufLike, PathInner, PathLike, ToPathOwned}};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Loc<'a, P: ?Sized + PathLike = Path> {
|
||||
pub(super) inner: &'a P,
|
||||
pub(super) uri: usize,
|
||||
pub(super) urn: usize,
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Loc<'p, P = &'p Path> {
|
||||
pub(super) inner: P,
|
||||
pub(super) uri: usize,
|
||||
pub(super) urn: usize,
|
||||
pub(super) _phantom: PhantomData<&'p ()>,
|
||||
}
|
||||
|
||||
impl<'a, P> Copy for Loc<'a, P> where P: ?Sized + PathLike {}
|
||||
|
||||
impl<'a, P> Clone for Loc<'a, P>
|
||||
impl<'p, P> Default for Loc<'p, P>
|
||||
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
|
||||
P: ?Sized + PathLike,
|
||||
{
|
||||
fn default() -> Self { Self { inner: P::default(), uri: 0, urn: 0 } }
|
||||
}
|
||||
|
||||
impl<P> Deref for Loc<'_, P>
|
||||
where
|
||||
P: ?Sized + PathLike,
|
||||
P: PathLike<'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>
|
||||
where
|
||||
P: ?Sized + PathLike,
|
||||
{
|
||||
fn as_ref(&self) -> &P { self.inner }
|
||||
// FIXME: remove
|
||||
impl AsRef<std::path::Path> for Loc<'_, &std::path::Path> {
|
||||
fn as_ref(&self) -> &std::path::Path { self.inner }
|
||||
}
|
||||
|
||||
// --- Hash
|
||||
impl<P> Hash for Loc<'_, P>
|
||||
impl<'p, P> Hash for Loc<'p, P>
|
||||
where
|
||||
P: ?Sized + PathLike + Hash,
|
||||
P: PathLike<'p> + Hash,
|
||||
{
|
||||
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
|
||||
P: ?Sized + PathLike,
|
||||
T: ?Sized + AsRef<P>,
|
||||
P: PathLike<'p> + ToPathOwned<<P as PathLike<'p>>::Owned>,
|
||||
<P as PathLike<'p>>::Owned: PathBufLike,
|
||||
{
|
||||
fn from(value: &'a T) -> Self {
|
||||
let path = value.as_ref();
|
||||
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 }
|
||||
fn from(value: Loc<'p, P>) -> Self {
|
||||
Self { inner: value.inner.to_path_owned(), uri: value.uri, urn: value.urn }
|
||||
}
|
||||
}
|
||||
|
||||
// --- Eq
|
||||
impl<P> PartialEq for Loc<'_, P>
|
||||
impl<'p, P> PartialEq for Loc<'p, P>
|
||||
where
|
||||
P: ?Sized + PathLike + PartialEq,
|
||||
P: PathLike<'p> + PartialEq,
|
||||
{
|
||||
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
|
||||
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
|
||||
T: AsRef<P> + ?Sized,
|
||||
U: AsRef<P> + ?Sized,
|
||||
T: AsPathView<'p, P>,
|
||||
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.urn = loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").len();
|
||||
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
|
||||
T: ?Sized + AsRef<P>,
|
||||
<P as PathLike>::Components<'a>: AsRef<P> + Clone + DoubleEndedIterator,
|
||||
T: AsPathView<'p, P>,
|
||||
{
|
||||
if urn > uri {
|
||||
bail!("URN cannot be longer than URI");
|
||||
}
|
||||
|
||||
let mut loc = Self::from(path);
|
||||
let mut loc = Self::bare(path);
|
||||
if uri == 0 {
|
||||
(loc.uri, loc.urn) = (0, 0);
|
||||
return Ok(loc);
|
||||
|
|
@ -143,21 +108,44 @@ where
|
|||
Ok(loc)
|
||||
}
|
||||
|
||||
pub fn zeroed<T>(path: &'a T) -> Self
|
||||
pub fn bare<T>(path: T) -> Self
|
||||
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
|
||||
}
|
||||
|
||||
pub fn floated<T, U>(path: &'a T, base: &U) -> Self
|
||||
pub fn floated<'a, T, U>(path: T, base: U) -> Self
|
||||
where
|
||||
T: AsRef<P> + ?Sized,
|
||||
U: AsRef<P> + ?Sized,
|
||||
T: AsPathView<'p, P>,
|
||||
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
|
||||
}
|
||||
|
|
@ -166,24 +154,24 @@ where
|
|||
pub fn as_loc(self) -> Self { self }
|
||||
|
||||
#[inline]
|
||||
pub fn as_path(self) -> &'a P { self.inner }
|
||||
pub fn as_path(self) -> P { self.inner }
|
||||
|
||||
#[inline]
|
||||
pub fn uri(self) -> &'a P {
|
||||
pub fn uri(self) -> P {
|
||||
unsafe {
|
||||
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.uri..))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn urn(self) -> &'a P {
|
||||
pub fn urn(self) -> P {
|
||||
unsafe {
|
||||
P::from_encoded_bytes(self.inner.encoded_bytes().get_unchecked(self.inner.len() - self.urn..))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn base(self) -> &'a P {
|
||||
pub fn base(self) -> P {
|
||||
unsafe {
|
||||
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 }
|
||||
|
||||
#[inline]
|
||||
pub fn trail(self) -> &'a P {
|
||||
pub fn trail(self) -> P {
|
||||
unsafe {
|
||||
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 }
|
||||
|
||||
#[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]
|
||||
pub fn stem(self) -> Option<&'a P::Inner> { self.inner.file_stem() }
|
||||
pub fn stem(self) -> Option<P::Inner> { self.inner.file_stem() }
|
||||
|
||||
#[inline]
|
||||
pub fn ext(self) -> Option<&'a P::Inner> { self.inner.extension() }
|
||||
pub fn ext(self) -> Option<P::Inner> { self.inner.extension() }
|
||||
|
||||
#[inline]
|
||||
pub fn parent(self) -> Option<&'a P> { self.inner.parent() }
|
||||
pub fn parent(self) -> Option<P> { self.inner.parent() }
|
||||
|
||||
#[inline]
|
||||
pub fn triple(self) -> (&'a P, &'a P, &'a P) {
|
||||
pub fn triple(self) -> (P, P, P) {
|
||||
let len = self.inner.len();
|
||||
|
||||
let base = ..len - self.uri;
|
||||
|
|
@ -232,9 +220,9 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn strip_prefix<T>(self, base: T) -> Option<&'a P>
|
||||
pub fn strip_prefix<'a, T>(self, base: T) -> Option<P>
|
||||
where
|
||||
T: AsRef<P>,
|
||||
T: AsPathView<'a, P::View<'a>>,
|
||||
{
|
||||
self.inner.strip_prefix(base)
|
||||
}
|
||||
|
|
|
|||
45
yazi-shared/src/path/buf.rs
Normal file
45
yazi-shared/src/path/buf.rs
Normal 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());
|
||||
}
|
||||
}
|
||||
0
yazi-shared/src/path/component.rs
Normal file
0
yazi-shared/src/path/component.rs
Normal file
0
yazi-shared/src/path/components.rs
Normal file
0
yazi-shared/src/path/components.rs
Normal file
9
yazi-shared/src/path/dyn.rs
Normal file
9
yazi-shared/src/path/dyn.rs
Normal 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),
|
||||
}
|
||||
13
yazi-shared/src/path/inner.rs
Normal file
13
yazi-shared/src/path/inner.rs
Normal 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 }
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
yazi_macro::mod_flat!(traits);
|
||||
yazi_macro::mod_flat!(buf component components inner path r#dyn traits);
|
||||
|
|
|
|||
81
yazi-shared/src/path/path.rs
Normal file
81
yazi-shared/src/path/path.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,147 +1,90 @@
|
|||
use std::{ffi::{OsStr, OsString}, path::{Path, PathBuf}};
|
||||
use crate::path::PathLike;
|
||||
|
||||
pub trait AsPath {
|
||||
fn as_path(&self) -> &(impl ?Sized + PathLike);
|
||||
fn as_path(&self) -> impl PathLike<'_>;
|
||||
}
|
||||
|
||||
pub trait PathLike: AsRef<Self> {
|
||||
type Inner: ?Sized + PathInner;
|
||||
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>;
|
||||
impl AsPath for &std::ffi::OsStr {
|
||||
fn as_path(&self) -> impl PathLike<'_> { std::path::Path::new(self) }
|
||||
}
|
||||
|
||||
pub trait PathBufLike: AsRef<Self::Borrowed> + Default + 'static {
|
||||
type Inner: AsRef<Self::InnerRef>;
|
||||
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>;
|
||||
impl AsPath for &std::path::Path {
|
||||
fn as_path(&self) -> impl PathLike<'_> { *self }
|
||||
}
|
||||
|
||||
pub trait PathInner {
|
||||
fn len(&self) -> usize { self.encoded_bytes().len() }
|
||||
|
||||
fn encoded_bytes(&self) -> &[u8];
|
||||
impl AsPath for std::path::PathBuf {
|
||||
fn as_path(&self) -> impl PathLike<'_> { self.as_path() }
|
||||
}
|
||||
|
||||
impl AsPath for &OsStr {
|
||||
fn as_path(&self) -> &(impl ?Sized + PathLike) { Path::new(self) }
|
||||
impl AsPath for &std::path::PathBuf {
|
||||
fn as_path(&self) -> impl PathLike<'_> { (*self).as_path() }
|
||||
}
|
||||
|
||||
impl AsPath for &Path {
|
||||
fn as_path(&self) -> &(impl ?Sized + PathLike) { *self }
|
||||
// --- AsPathView
|
||||
pub trait AsPathView<'a, T> {
|
||||
fn as_path_view(self) -> T;
|
||||
}
|
||||
|
||||
impl AsPath for PathBuf {
|
||||
fn as_path(&self) -> &(impl ?Sized + PathLike) { self.as_path() }
|
||||
impl<'a> AsPathView<'a, &'a std::path::Path> for &'a str {
|
||||
fn as_path_view(self) -> &'a std::path::Path { std::path::Path::new(self) }
|
||||
}
|
||||
|
||||
impl AsPath for &PathBuf {
|
||||
fn as_path(&self) -> &(impl ?Sized + PathLike) { (*self).as_path() }
|
||||
impl<'a> AsPathView<'a, &'a std::path::Path> for &'a std::path::Path {
|
||||
fn as_path_view(self) -> &'a std::path::Path { self }
|
||||
}
|
||||
|
||||
impl PathLike for Path {
|
||||
type Components<'a> = std::path::Components<'a>;
|
||||
type Inner = OsStr;
|
||||
type Owned = PathBuf;
|
||||
impl<'a> AsPathView<'a, &'a std::path::Path> for &'a std::path::PathBuf {
|
||||
fn as_path_view(self) -> &'a std::path::Path { self }
|
||||
}
|
||||
|
||||
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("") }
|
||||
|
||||
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<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<'a> AsPathView<'a, super::PathDyn<'a>> for &'a super::PathBufDyn {
|
||||
fn as_path_view(self) -> super::PathDyn<'a> {
|
||||
match self {
|
||||
super::PathBufDyn::Os(p) => super::PathDyn::Os(p.as_path()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<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<'a> AsPathView<'a, &'a std::path::Path> for crate::loc::Loc<'a, &'a std::path::Path> {
|
||||
fn as_path_view(self) -> &'a std::path::Path { *self }
|
||||
}
|
||||
|
||||
impl PathInner for OsStr {
|
||||
fn encoded_bytes(&self) -> &[u8] { self.as_encoded_bytes() }
|
||||
// --- ToPathOwned
|
||||
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() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ impl UrlBuf {
|
|||
}
|
||||
|
||||
#[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]
|
||||
pub fn rebase(&self, base: &Path) -> Self {
|
||||
|
|
@ -125,14 +125,14 @@ impl UrlBuf {
|
|||
#[inline]
|
||||
pub fn to_search(&self, domain: impl AsRef<str>) -> Self {
|
||||
Self {
|
||||
loc: LocBuf::zeroed(self.loc.to_path()),
|
||||
loc: LocBuf::<PathBuf>::zeroed(self.loc.to_path()),
|
||||
scheme: Scheme::Search(Pool::<str>::intern(domain)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,12 +49,14 @@ impl<'a> TryFrom<&'a [u8]> for UrlCow<'a> {
|
|||
let (scheme, path, port) = Self::parse(value)?;
|
||||
|
||||
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))) => {
|
||||
Self::Borrowed { loc: Loc::with(p, uri, urn)?, 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 }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
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
|
||||
pub trait AsUrl {
|
||||
|
|
@ -9,7 +9,7 @@ pub trait AsUrl {
|
|||
|
||||
impl AsUrl for Path {
|
||||
#[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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ impl Debug for Url<'_> {
|
|||
impl<'a> Url<'a> {
|
||||
#[inline]
|
||||
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]
|
||||
|
|
@ -42,7 +42,7 @@ impl<'a> Url<'a> {
|
|||
|
||||
#[inline]
|
||||
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]
|
||||
|
|
@ -71,8 +71,8 @@ impl<'a> Url<'a> {
|
|||
|
||||
let loc = match self.scheme {
|
||||
S::Regular => join.into(),
|
||||
S::Search(_) => LocBuf::new(join, self.loc.base(), self.loc.base()),
|
||||
S::Archive(_) => LocBuf::floated(join, self.loc.base()),
|
||||
S::Search(_) => LocBuf::<PathBuf>::new(join, self.loc.base(), self.loc.base()),
|
||||
S::Archive(_) => LocBuf::<PathBuf>::floated(join, self.loc.base()),
|
||||
S::Sftp(_) => join.into(),
|
||||
};
|
||||
|
||||
|
|
@ -134,7 +134,7 @@ impl<'a> Url<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let loc: Loc = self.loc.base().into();
|
||||
let loc = Loc::bare(self.loc.base());
|
||||
Some(match self.scheme {
|
||||
S::Regular => Self { loc, scheme: S::Regular },
|
||||
S::Search(_) => Self { loc, scheme: self.scheme },
|
||||
|
|
@ -151,11 +151,11 @@ impl<'a> Url<'a> {
|
|||
|
||||
Some(match self.scheme {
|
||||
// Regular
|
||||
S::Regular => Self { loc: parent.into(), scheme: S::Regular },
|
||||
S::Regular => Self { loc: Loc::bare(parent), scheme: S::Regular },
|
||||
|
||||
// Search
|
||||
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(_) => {
|
||||
Self { loc: Loc::new(parent, self.loc.base(), self.loc.base()), scheme: self.scheme }
|
||||
|
|
@ -163,7 +163,7 @@ impl<'a> Url<'a> {
|
|||
|
||||
// Archive
|
||||
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() => {
|
||||
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 },
|
||||
|
||||
// SFTP
|
||||
S::Sftp(_) => Self { loc: parent.into(), scheme: self.scheme },
|
||||
S::Sftp(_) => Self { loc: Loc::bare(parent), scheme: self.scheme },
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue