diff --git a/yazi-actor/src/cmp/trigger.rs b/yazi-actor/src/cmp/trigger.rs index 7d1f55f9..04172b80 100644 --- a/yazi-actor/src/cmp/trigger.rs +++ b/yazi-actor/src/cmp/trigger.rs @@ -5,7 +5,7 @@ use yazi_fs::{CWD, path::expand_url, provider}; use yazi_macro::{act, render, succ}; use yazi_parser::cmp::{CmpItem, ShowOpt, TriggerOpt}; use yazi_proxy::CmpProxy; -use yazi_shared::{OsStrSplit, event::Data, natsort, url::{Url, UrnBuf}}; +use yazi_shared::{OsStrSplit, event::Data, natsort, url::{UrlBuf, UrnBuf}}; use crate::{Actor, Ctx}; @@ -66,8 +66,8 @@ impl Actor for Trigger { } impl Trigger { - fn split_url(s: &str) -> Option<(Url, UrnBuf)> { - let (scheme, path, ..) = Url::parse(s.as_bytes()).ok()?; + fn split_url(s: &str) -> Option<(UrlBuf, UrnBuf)> { + let (scheme, path, ..) = UrlBuf::parse(s.as_bytes()).ok()?; if !scheme.is_virtual() && path.as_os_str() == "~" { return None; // We don't autocomplete a `~`, but `~/` @@ -79,8 +79,8 @@ impl Trigger { const SEP: char = std::path::MAIN_SEPARATOR; Some(match path.as_os_str().rsplit_once(SEP) { - Some((p, c)) if p.is_empty() => (Url { loc: MAIN_SEPARATOR_STR.into(), scheme }, c.into()), - Some((p, c)) => (expand_url(Url { loc: p.into(), scheme }), c.into()), + Some((p, c)) if p.is_empty() => (UrlBuf { loc: MAIN_SEPARATOR_STR.into(), scheme }, c.into()), + Some((p, c)) => (expand_url(UrlBuf { loc: p.into(), scheme }), c.into()), None => (CWD.load().as_ref().clone(), path.into()), }) } @@ -95,7 +95,7 @@ mod tests { fn compare(s: &str, parent: &str, child: &str) { let (mut p, c) = Trigger::split_url(s).unwrap(); if let Some(u) = p.strip_prefix(yazi_fs::CWD.load().as_ref()) { - p = Url::from(&**u); + p = UrlBuf::from(&**u); } assert_eq!((p, c.as_urn()), (parent.parse().unwrap(), Urn::new(child))); } diff --git a/yazi-actor/src/context.rs b/yazi-actor/src/context.rs index 82d87fe3..9b8079f8 100644 --- a/yazi-actor/src/context.rs +++ b/yazi-actor/src/context.rs @@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut}; use anyhow::{Result, anyhow}; use yazi_core::{Core, mgr::Tabs, tab::{Folder, Tab}, tasks::Tasks}; use yazi_fs::File; -use yazi_shared::{Source, event::Cmd, url::Url}; +use yazi_shared::{Source, event::Cmd, url::UrlBuf}; pub struct Ctx<'a> { pub core: &'a mut Core, @@ -68,7 +68,7 @@ impl<'a> Ctx<'a> { pub fn tab_mut(&mut self) -> &mut Tab { &mut self.core.mgr.tabs[self.tab] } #[inline] - pub fn cwd(&self) -> &Url { self.tab().cwd() } + pub fn cwd(&self) -> &UrlBuf { self.tab().cwd() } #[inline] pub fn parent(&self) -> Option<&Folder> { self.tab().parent.as_ref() } diff --git a/yazi-actor/src/mgr/bulk_rename.rs b/yazi-actor/src/mgr/bulk_rename.rs index 0214252f..3e8e805a 100644 --- a/yazi-actor/src/mgr/bulk_rename.rs +++ b/yazi-actor/src/mgr/bulk_rename.rs @@ -10,7 +10,7 @@ use yazi_fs::{File, FilesOp, max_common_root, maybe_exists, path::skip_url, path use yazi_macro::{err, succ}; use yazi_parser::VoidOpt; use yazi_proxy::{AppProxy, HIDER, TasksProxy, WATCHER}; -use yazi_shared::{OsStrJoin, event::Data, terminal_clear, url::{Component, Url}}; +use yazi_shared::{OsStrJoin, event::Data, terminal_clear, url::{Component, UrlBuf}}; use yazi_term::tty::TTY; use crate::{Actor, Ctx}; @@ -73,7 +73,12 @@ impl Actor for BulkRename { } impl BulkRename { - async fn r#do(root: usize, old: Vec, new: Vec, selected: Vec) -> Result<()> { + async fn r#do( + root: usize, + old: Vec, + new: Vec, + selected: Vec, + ) -> Result<()> { terminal_clear(TTY.writer())?; if old.len() != new.len() { #[rustfmt::skip] @@ -108,7 +113,7 @@ impl BulkRename { let permit = WATCHER.acquire().await.unwrap(); let (mut failed, mut succeeded) = (Vec::new(), HashMap::with_capacity(todo.len())); for (o, n) in todo { - let (old, new): (Url, Url) = ( + let (old, new): (UrlBuf, UrlBuf) = ( selected[o.0].components().take(root).chain([Component::Normal(&o)]).collect(), selected[n.0].components().take(root).chain([Component::Normal(&n)]).collect(), ); @@ -138,7 +143,7 @@ impl BulkRename { } fn opener() -> Option<&'static OpenerRule> { - YAZI.opener.block(YAZI.open.all(Url::from(Path::new("bulk-rename.txt")), "text/plain")) + YAZI.opener.block(YAZI.open.all(UrlBuf::from(Path::new("bulk-rename.txt")), "text/plain")) } async fn output_failed(failed: Vec<(Tuple, Tuple, anyhow::Error)>) -> Result<()> { diff --git a/yazi-actor/src/mgr/cd.rs b/yazi-actor/src/mgr/cd.rs index 6d4a3b34..e7c0714c 100644 --- a/yazi-actor/src/mgr/cd.rs +++ b/yazi-actor/src/mgr/cd.rs @@ -9,7 +9,7 @@ use yazi_fs::{File, FilesOp, path::expand_url}; use yazi_macro::{act, err, render, succ}; use yazi_parser::mgr::CdOpt; use yazi_proxy::{CmpProxy, InputProxy, MgrProxy}; -use yazi_shared::{Debounce, errors::InputError, event::Data, url::Url}; +use yazi_shared::{Debounce, errors::InputError, event::Data, url::UrlBuf}; use crate::{Actor, Ctx}; @@ -76,7 +76,7 @@ impl Cd { while let Some(result) = rx.next().await { match result { Ok(s) => { - let Ok(url) = Url::try_from(s).map(expand_url) else { return }; + let Ok(url) = UrlBuf::try_from(s).map(expand_url) else { return }; let Ok(file) = File::new(url.clone()).await else { return }; if file.is_dir() { diff --git a/yazi-actor/src/mgr/create.rs b/yazi-actor/src/mgr/create.rs index 791b5a9b..1f7a620f 100644 --- a/yazi-actor/src/mgr/create.rs +++ b/yazi-actor/src/mgr/create.rs @@ -4,7 +4,7 @@ use yazi_fs::{File, FilesOp, maybe_exists, ok_or_not_found, provider, realname}; use yazi_macro::succ; use yazi_parser::mgr::CreateOpt; use yazi_proxy::{ConfirmProxy, InputProxy, MgrProxy, WATCHER}; -use yazi_shared::{event::Data, url::{Url, UrnBuf}}; +use yazi_shared::{event::Data, url::{UrlBuf, UrnBuf}}; use crate::{Actor, Ctx}; @@ -40,7 +40,7 @@ impl Actor for Create { } impl Create { - async fn r#do(new: Url, dir: bool) -> Result<()> { + async fn r#do(new: UrlBuf, dir: bool) -> Result<()> { let Some(parent) = new.parent_url() else { return Ok(()) }; let _permit = WATCHER.acquire().await.unwrap(); diff --git a/yazi-actor/src/mgr/open.rs b/yazi-actor/src/mgr/open.rs index 00a6c570..8803554e 100644 --- a/yazi-actor/src/mgr/open.rs +++ b/yazi-actor/src/mgr/open.rs @@ -9,7 +9,7 @@ use yazi_macro::{act, succ}; use yazi_parser::mgr::{OpenDoOpt, OpenOpt}; use yazi_plugin::isolate; use yazi_proxy::{MgrProxy, PickProxy, TasksProxy}; -use yazi_shared::{MIME_DIR, event::{CmdCow, Data}, url::Url}; +use yazi_shared::{MIME_DIR, event::{CmdCow, Data}, url::UrlBuf}; use crate::{Actor, Ctx, mgr::Quit}; @@ -110,7 +110,7 @@ impl Actor for OpenDo { } impl Open { - fn guess_folder(cx: &Ctx, url: &Url) -> bool { + fn guess_folder(cx: &Ctx, url: &UrlBuf) -> bool { let Some(p) = url.parent_url() else { return true; }; diff --git a/yazi-actor/src/mgr/quit.rs b/yazi-actor/src/mgr/quit.rs index 02a72623..6d71b2e9 100644 --- a/yazi-actor/src/mgr/quit.rs +++ b/yazi-actor/src/mgr/quit.rs @@ -8,7 +8,7 @@ use yazi_dds::spark::SparkKind; use yazi_macro::{emit, succ}; use yazi_parser::mgr::{OpenOpt, QuitOpt}; use yazi_proxy::ConfirmProxy; -use yazi_shared::{event::{Data, EventQuit}, url::Url}; +use yazi_shared::{event::{Data, EventQuit}, url::UrlBuf}; use crate::{Actor, Ctx}; @@ -69,7 +69,7 @@ impl Actor for Quit { impl Quit { pub(super) fn quit_with_selected<'a, I>(opt: OpenOpt, selected: I) -> bool where - I: Iterator, + I: Iterator, { if opt.interactive || ARGS.chooser_file.is_none() { return false; diff --git a/yazi-actor/src/mgr/rename.rs b/yazi-actor/src/mgr/rename.rs index dae3ca76..4bd35b20 100644 --- a/yazi-actor/src/mgr/rename.rs +++ b/yazi-actor/src/mgr/rename.rs @@ -5,7 +5,7 @@ use yazi_fs::{File, FilesOp, maybe_exists, ok_or_not_found, paths_to_same_file, use yazi_macro::{act, err, succ}; use yazi_parser::mgr::RenameOpt; use yazi_proxy::{ConfirmProxy, InputProxy, MgrProxy, WATCHER}; -use yazi_shared::{Id, event::Data, url::{Url, UrnBuf}}; +use yazi_shared::{Id, event::Data, url::{UrlBuf, UrnBuf}}; use crate::{Actor, Ctx}; @@ -47,7 +47,7 @@ impl Actor for Rename { return; } - let new = Url::from(old.parent().unwrap().join(name)); + let new = UrlBuf::from(old.parent().unwrap().join(name)); if opt.force || !maybe_exists(&new).await || paths_to_same_file(&old, &new).await { Self::r#do(tab, old, new).await.ok(); } else if ConfirmProxy::show(ConfirmCfg::overwrite(&new)).await { @@ -59,7 +59,7 @@ impl Actor for Rename { } impl Rename { - async fn r#do(tab: Id, old: Url, new: Url) -> Result<()> { + async fn r#do(tab: Id, old: UrlBuf, new: UrlBuf) -> Result<()> { let Some((p_old, n_old)) = old.pair() else { return Ok(()) }; let Some((p_new, n_new)) = new.pair() else { return Ok(()) }; let _permit = WATCHER.acquire().await.unwrap(); @@ -85,7 +85,7 @@ impl Rename { Ok(()) } - fn empty_url_part(url: &Url, by: &str) -> String { + fn empty_url_part(url: &UrlBuf, by: &str) -> String { if by == "all" { return String::new(); } diff --git a/yazi-actor/src/mgr/yank.rs b/yazi-actor/src/mgr/yank.rs index a68368b8..5afc94a4 100644 --- a/yazi-actor/src/mgr/yank.rs +++ b/yazi-actor/src/mgr/yank.rs @@ -2,7 +2,7 @@ use anyhow::Result; use yazi_core::mgr::Yanked; use yazi_macro::{act, render}; use yazi_parser::mgr::YankOpt; -use yazi_shared::{event::Data, url::CovUrl}; +use yazi_shared::{event::Data, url::UrlCov}; use crate::{Actor, Ctx}; @@ -17,7 +17,7 @@ impl Actor for Yank { act!(mgr:escape_visual, cx)?; cx.mgr.yanked = - Yanked::new(opt.cut, cx.tab().selected_or_hovered().cloned().map(CovUrl).collect()); + Yanked::new(opt.cut, cx.tab().selected_or_hovered().cloned().map(UrlCov).collect()); render!(cx.mgr.yanked.catchup_revision(true)); act!(mgr:escape_select, cx) diff --git a/yazi-adapter/src/adapter.rs b/yazi-adapter/src/adapter.rs index 582091a5..059e71d3 100644 --- a/yazi-adapter/src/adapter.rs +++ b/yazi-adapter/src/adapter.rs @@ -3,7 +3,7 @@ use std::{env, fmt::Display}; use anyhow::Result; use ratatui::layout::Rect; use tracing::warn; -use yazi_shared::{env_exists, url::Url}; +use yazi_shared::{env_exists, url::UrlBuf}; use crate::{Emulator, SHOWN, TMUX, drivers}; @@ -35,7 +35,7 @@ impl Display for Adapter { } impl Adapter { - pub async fn image_show(self, url: &Url, max: Rect) -> Result { + pub async fn image_show(self, url: &UrlBuf, max: Rect) -> Result { if max.is_empty() { return Ok(Rect::default()); } diff --git a/yazi-adapter/src/drivers/iip.rs b/yazi-adapter/src/drivers/iip.rs index 8295326b..840ab273 100644 --- a/yazi-adapter/src/drivers/iip.rs +++ b/yazi-adapter/src/drivers/iip.rs @@ -6,14 +6,14 @@ use crossterm::{cursor::MoveTo, queue}; use image::{DynamicImage, ExtendedColorType, ImageEncoder, codecs::{jpeg::JpegEncoder, png::PngEncoder}}; use ratatui::layout::Rect; use yazi_config::YAZI; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use crate::{CLOSE, Emulator, Image, START, adapter::Adapter}; pub(crate) struct Iip; impl Iip { - pub(crate) async fn image_show(url: &Url, max: Rect) -> Result { + pub(crate) async fn image_show(url: &UrlBuf, max: Rect) -> Result { let img = Image::downscale(url, max).await?; let area = Image::pixel_area((img.width(), img.height()), max); let b = Self::encode(img).await?; diff --git a/yazi-adapter/src/drivers/kgp.rs b/yazi-adapter/src/drivers/kgp.rs index b05ff992..bcf25cec 100644 --- a/yazi-adapter/src/drivers/kgp.rs +++ b/yazi-adapter/src/drivers/kgp.rs @@ -6,7 +6,7 @@ use base64::{Engine, engine::general_purpose}; use crossterm::{cursor::MoveTo, queue}; use image::DynamicImage; use ratatui::layout::Rect; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use crate::{CLOSE, ESCAPE, Emulator, START, adapter::Adapter, image::Image}; @@ -313,7 +313,7 @@ static DIACRITICS: [char; 297] = [ pub(crate) struct Kgp; impl Kgp { - pub(crate) async fn image_show(url: &Url, max: Rect) -> Result { + pub(crate) async fn image_show(url: &UrlBuf, max: Rect) -> Result { let img = Image::downscale(url, max).await?; let area = Image::pixel_area((img.width(), img.height()), max); diff --git a/yazi-adapter/src/drivers/kgp_old.rs b/yazi-adapter/src/drivers/kgp_old.rs index 89865b45..25b175bc 100644 --- a/yazi-adapter/src/drivers/kgp_old.rs +++ b/yazi-adapter/src/drivers/kgp_old.rs @@ -5,7 +5,7 @@ use anyhow::Result; use base64::{Engine, engine::general_purpose}; use image::DynamicImage; use ratatui::layout::Rect; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use yazi_term::tty::TTY; use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter}; @@ -13,7 +13,7 @@ use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter}; pub(crate) struct KgpOld; impl KgpOld { - pub(crate) async fn image_show(url: &Url, max: Rect) -> Result { + pub(crate) async fn image_show(url: &UrlBuf, max: Rect) -> Result { let img = Image::downscale(url, max).await?; let area = Image::pixel_area((img.width(), img.height()), max); let b = Self::encode(img).await?; diff --git a/yazi-adapter/src/drivers/sixel.rs b/yazi-adapter/src/drivers/sixel.rs index 79876626..9477a8f6 100644 --- a/yazi-adapter/src/drivers/sixel.rs +++ b/yazi-adapter/src/drivers/sixel.rs @@ -6,14 +6,14 @@ use image::{DynamicImage, GenericImageView, RgbImage}; use palette::{Srgb, cast::ComponentsAs}; use quantette::{ColorSlice, PaletteSize, QuantizeOutput, wu::UIntBinner}; use ratatui::layout::Rect; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use crate::{CLOSE, ESCAPE, Emulator, Image, START, adapter::Adapter}; pub(crate) struct Sixel; impl Sixel { - pub(crate) async fn image_show(url: &Url, max: Rect) -> Result { + pub(crate) async fn image_show(url: &UrlBuf, max: Rect) -> Result { let img = Image::downscale(url, max).await?; let area = Image::pixel_area((img.width(), img.height()), max); let b = Self::encode(img).await?; diff --git a/yazi-adapter/src/image.rs b/yazi-adapter/src/image.rs index 6a779a7c..8d2ab112 100644 --- a/yazi-adapter/src/image.rs +++ b/yazi-adapter/src/image.rs @@ -3,14 +3,14 @@ use image::{DynamicImage, ExtendedColorType, ImageDecoder, ImageEncoder, ImageEr use ratatui::layout::Rect; use yazi_config::YAZI; use yazi_fs::provider; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use crate::Dimension; pub struct Image; impl Image { - pub async fn precache(src: &Url, cache: &Url) -> Result<()> { + pub async fn precache(src: &UrlBuf, cache: &UrlBuf) -> Result<()> { let (mut img, orientation, icc) = Self::decode_from(src).await?; let (w, h) = Self::flip_size(orientation, (YAZI.preview.max_width, YAZI.preview.max_height)); @@ -41,7 +41,7 @@ impl Image { Ok(provider::write(cache, buf).await?) } - pub(super) async fn downscale(url: &Url, rect: Rect) -> Result { + pub(super) async fn downscale(url: &UrlBuf, rect: Rect) -> Result { let (mut img, orientation, _) = Self::decode_from(url).await?; let (w, h) = Self::flip_size(orientation, Self::max_pixel(rect)); @@ -96,7 +96,7 @@ impl Image { } } - async fn decode_from(url: &Url) -> ImageResult<(DynamicImage, Orientation, Option>)> { + async fn decode_from(url: &UrlBuf) -> ImageResult<(DynamicImage, Orientation, Option>)> { let mut limits = Limits::no_limits(); if YAZI.tasks.image_alloc > 0 { limits.max_alloc = Some(YAZI.tasks.image_alloc as u64); diff --git a/yazi-binding/src/url.rs b/yazi-binding/src/url.rs index 0dde1e69..bd490a07 100644 --- a/yazi-binding/src/url.rs +++ b/yazi-binding/src/url.rs @@ -1,14 +1,14 @@ use std::{borrow::Cow, ops::Deref}; use mlua::{AnyUserData, ExternalError, FromLua, Lua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef, Value}; -use yazi_shared::url::CovUrl; +use yazi_shared::url::UrlCov; use crate::{Urn, cached_field, deprecate}; pub type UrlRef = UserDataRef; pub struct Url { - inner: yazi_shared::url::Url, + inner: yazi_shared::url::UrlBuf, v_name: Option, v_stem: Option, @@ -20,41 +20,41 @@ pub struct Url { } impl Deref for Url { - type Target = yazi_shared::url::Url; + type Target = yazi_shared::url::UrlBuf; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef for Url { - fn as_ref(&self) -> &yazi_shared::url::Url { &self.inner } +impl AsRef for Url { + fn as_ref(&self) -> &yazi_shared::url::UrlBuf { &self.inner } } -impl From for yazi_shared::url::Url { +impl From for yazi_shared::url::UrlBuf { fn from(value: Url) -> Self { value.inner } } -impl From for Cow<'_, yazi_shared::url::Url> { +impl From for Cow<'_, yazi_shared::url::UrlBuf> { fn from(value: Url) -> Self { Cow::Owned(value.inner) } } -impl<'a> From<&'a Url> for Cow<'a, yazi_shared::url::Url> { +impl<'a> From<&'a Url> for Cow<'a, yazi_shared::url::UrlBuf> { fn from(value: &'a Url) -> Self { Cow::Borrowed(&value.inner) } } -impl From for yazi_shared::url::CovUrl { - fn from(value: Url) -> Self { CovUrl(value.inner) } +impl From for yazi_shared::url::UrlCov { + fn from(value: Url) -> Self { UrlCov(value.inner) } } impl TryFrom<&[u8]> for Url { type Error = mlua::Error; fn try_from(value: &[u8]) -> mlua::Result { - Ok(Self::new(yazi_shared::url::Url::try_from(value)?)) + Ok(Self::new(yazi_shared::url::UrlBuf::try_from(value)?)) } } impl Url { - pub fn new(url: impl Into) -> Self { + pub fn new(url: impl Into) -> Self { Self { inner: url.into(), @@ -104,9 +104,7 @@ impl UserData for Url { }); cached_field!(fields, parent, |_, me| Ok(me.parent_url().map(Self::new))); cached_field!(fields, urn, |_, me| Ok(Urn::new(me.urn_owned()))); - cached_field!(fields, base, |_, me| { - Ok(if me.base().as_os_str().is_empty() { None } else { Some(Self::new(me.base())) }) - }); + cached_field!(fields, base, |_, me| Ok(me.base().map(Self::new))); cached_field!(fields, domain, |lua, me| { me.scheme.domain().map(|s| lua.create_string(s)).transpose() }); diff --git a/yazi-boot/src/actions/debug.rs b/yazi-boot/src/actions/debug.rs index 8d956249..bc5bc7ae 100644 --- a/yazi-boot/src/actions/debug.rs +++ b/yazi-boot/src/actions/debug.rs @@ -3,7 +3,7 @@ use std::{env, ffi::OsStr, fmt::Write, path::Path}; use regex::Regex; use yazi_adapter::Mux; use yazi_config::YAZI; -use yazi_shared::{timestamp_us, url::Url}; +use yazi_shared::{timestamp_us, url::UrlBuf}; use super::Actions; @@ -58,17 +58,17 @@ impl Actions { writeln!( s, " default : {:?}", - YAZI.opener.first(YAZI.open.all(Url::from(Path::new("f75a.txt")), "text/plain")) + YAZI.opener.first(YAZI.open.all(UrlBuf::from(Path::new("f75a.txt")), "text/plain")) )?; writeln!( s, " block-create: {:?}", - YAZI.opener.block(YAZI.open.all(Url::from(Path::new("bulk-create.txt")), "text/plain")) + YAZI.opener.block(YAZI.open.all(UrlBuf::from(Path::new("bulk-create.txt")), "text/plain")) )?; writeln!( s, " block-rename: {:?}", - YAZI.opener.block(YAZI.open.all(Url::from(Path::new("bulk-rename.txt")), "text/plain")) + YAZI.opener.block(YAZI.open.all(UrlBuf::from(Path::new("bulk-rename.txt")), "text/plain")) )?; writeln!(s, "\nMultiplexers")?; diff --git a/yazi-boot/src/args.rs b/yazi-boot/src/args.rs index dbc921df..76de82ae 100644 --- a/yazi-boot/src/args.rs +++ b/yazi-boot/src/args.rs @@ -1,14 +1,14 @@ use std::path::PathBuf; use clap::{Parser, command}; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; #[derive(Debug, Default, Parser)] #[command(name = "yazi")] pub struct Args { /// Set the current working entry #[arg(index = 1, num_args = 1..=9)] - pub entries: Vec, + pub entries: Vec, /// Write the cwd on exit to this file #[arg(long)] diff --git a/yazi-boot/src/boot.rs b/yazi-boot/src/boot.rs index 8b20d9f5..2a291f7e 100644 --- a/yazi-boot/src/boot.rs +++ b/yazi-boot/src/boot.rs @@ -3,11 +3,11 @@ use std::{collections::HashSet, path::PathBuf}; use futures::executor::block_on; use serde::Serialize; use yazi_fs::{CWD, Xdg, path::expand_url, provider}; -use yazi_shared::url::{Url, UrnBuf}; +use yazi_shared::url::{UrlBuf, UrnBuf}; #[derive(Debug, Default, Serialize)] pub struct Boot { - pub cwds: Vec, + pub cwds: Vec, pub files: Vec, pub local_events: HashSet, @@ -20,12 +20,12 @@ pub struct Boot { } impl Boot { - async fn parse_entries(entries: &[Url]) -> (Vec, Vec) { + async fn parse_entries(entries: &[UrlBuf]) -> (Vec, Vec) { if entries.is_empty() { return (vec![CWD.load().as_ref().clone()], vec![UrnBuf::default()]); } - async fn go<'a>(entry: Url) -> (Url, UrnBuf) { + async fn go<'a>(entry: UrlBuf) -> (UrlBuf, UrnBuf) { let Some((parent, child)) = entry.pair() else { return (entry, UrnBuf::default()); }; diff --git a/yazi-config/src/mgr/mgr.rs b/yazi-config/src/mgr/mgr.rs index 62d00093..8a7e137f 100644 --- a/yazi-config/src/mgr/mgr.rs +++ b/yazi-config/src/mgr/mgr.rs @@ -2,7 +2,7 @@ use anyhow::{Result, bail}; use serde::Deserialize; use yazi_codegen::DeserializeOver2; use yazi_fs::{CWD, SortBy}; -use yazi_shared::{SyncCell, url::Url}; +use yazi_shared::{SyncCell, url::UrlBuf}; use super::{MgrRatio, MouseEvents}; @@ -32,7 +32,7 @@ impl Mgr { return None; } - let home = Url::from(dirs::home_dir().unwrap_or_default()); + let home = UrlBuf::from(dirs::home_dir().unwrap_or_default()); let cwd = if let Some(u) = CWD.load().strip_prefix(home) { format!("~{}{}", std::path::MAIN_SEPARATOR, u.display()) } else { diff --git a/yazi-config/src/open/open.rs b/yazi-config/src/open/open.rs index 7775ec84..424a3c91 100644 --- a/yazi-config/src/open/open.rs +++ b/yazi-config/src/open/open.rs @@ -4,7 +4,7 @@ use anyhow::Result; use indexmap::IndexSet; use serde::Deserialize; use yazi_codegen::DeserializeOver2; -use yazi_shared::{MIME_DIR, url::Url}; +use yazi_shared::{MIME_DIR, url::UrlBuf}; use crate::{Preset, open::OpenRule}; @@ -27,7 +27,7 @@ impl Open { pub fn all<'a, 'b, P, M>(&'a self, url: P, mime: M) -> impl Iterator + 'b where 'a: 'b, - P: AsRef + 'b, + P: AsRef + 'b, M: AsRef + 'b, { let is_dir = mime.as_ref() == MIME_DIR; @@ -42,7 +42,10 @@ impl Open { .map(String::as_str) } - pub fn common<'a>(&'a self, targets: &[(impl AsRef, impl AsRef)]) -> IndexSet<&'a str> { + pub fn common<'a>( + &'a self, + targets: &[(impl AsRef, impl AsRef)], + ) -> IndexSet<&'a str> { let each: Vec> = targets .iter() .map(|(u, m)| self.all(u, m).collect::>()) diff --git a/yazi-config/src/pattern.rs b/yazi-config/src/pattern.rs index bdc07dc6..8d59c716 100644 --- a/yazi-config/src/pattern.rs +++ b/yazi-config/src/pattern.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use anyhow::Result; use globset::GlobBuilder; use serde::Deserialize; -use yazi_shared::url::{Scheme, Url}; +use yazi_shared::url::{Scheme, UrlBuf}; #[derive(Debug, Deserialize)] #[serde(try_from = "String")] @@ -18,7 +18,7 @@ pub struct Pattern { impl Pattern { #[inline] - pub fn match_url(&self, url: impl AsRef, is_dir: bool) -> bool { + pub fn match_url(&self, url: impl AsRef, is_dir: bool) -> bool { let url = url.as_ref(); if is_dir != self.is_dir { @@ -124,7 +124,7 @@ mod tests { use super::*; fn matches(glob: &str, url: &str) -> bool { - Pattern::from_str(glob).unwrap().match_url(Url::from_str(url).unwrap(), false) + Pattern::from_str(glob).unwrap().match_url(UrlBuf::from_str(url).unwrap(), false) } #[cfg(unix)] diff --git a/yazi-config/src/plugin/fetcher.rs b/yazi-config/src/plugin/fetcher.rs index 59e041d5..a4d0f14a 100644 --- a/yazi-config/src/plugin/fetcher.rs +++ b/yazi-config/src/plugin/fetcher.rs @@ -1,5 +1,5 @@ use serde::Deserialize; -use yazi_shared::{MIME_DIR, event::Cmd, url::Url}; +use yazi_shared::{MIME_DIR, event::Cmd, url::UrlBuf}; use crate::{Pattern, Priority}; @@ -18,7 +18,7 @@ pub struct Fetcher { impl Fetcher { #[inline] - pub fn matches(&self, url: &Url, mime: &str) -> bool { + pub fn matches(&self, url: &UrlBuf, mime: &str) -> bool { self.mime.as_ref().is_some_and(|p| p.match_mime(mime)) || self.url.as_ref().is_some_and(|p| p.match_url(url, mime == MIME_DIR)) } diff --git a/yazi-config/src/plugin/plugin.rs b/yazi-config/src/plugin/plugin.rs index d13bbd2a..01452606 100644 --- a/yazi-config/src/plugin/plugin.rs +++ b/yazi-config/src/plugin/plugin.rs @@ -5,7 +5,7 @@ use serde::Deserialize; use tracing::warn; use yazi_codegen::DeserializeOver2; use yazi_fs::File; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::{Fetcher, Preloader, Previewer, Spotter}; use crate::{Preset, plugin::MAX_PREWORKERS}; @@ -40,7 +40,7 @@ pub struct Plugin { impl Plugin { pub fn fetchers<'a, 'b: 'a>( &'b self, - url: &'a Url, + url: &'a UrlBuf, mime: &'a str, ) -> impl Iterator + 'a { let mut seen = HashSet::new(); @@ -69,13 +69,13 @@ impl Plugin { }) } - pub fn spotter(&self, url: &Url, mime: &str) -> Option<&Spotter> { + pub fn spotter(&self, url: &UrlBuf, mime: &str) -> Option<&Spotter> { self.spotters.iter().find(|&p| p.matches(url, mime)) } pub fn preloaders<'a, 'b: 'a>( &'b self, - url: &'a Url, + url: &'a UrlBuf, mime: &'a str, ) -> impl Iterator + 'a { let mut next = true; @@ -88,7 +88,7 @@ impl Plugin { }) } - pub fn previewer(&self, url: &Url, mime: &str) -> Option<&Previewer> { + pub fn previewer(&self, url: &UrlBuf, mime: &str) -> Option<&Previewer> { self.previewers.iter().find(|&p| p.matches(url, mime)) } } diff --git a/yazi-config/src/plugin/preloader.rs b/yazi-config/src/plugin/preloader.rs index 443c79b5..b7ed9e3e 100644 --- a/yazi-config/src/plugin/preloader.rs +++ b/yazi-config/src/plugin/preloader.rs @@ -1,5 +1,5 @@ use serde::Deserialize; -use yazi_shared::{MIME_DIR, event::Cmd, url::Url}; +use yazi_shared::{MIME_DIR, event::Cmd, url::UrlBuf}; use crate::{Pattern, Priority}; @@ -19,7 +19,7 @@ pub struct Preloader { impl Preloader { #[inline] - pub fn matches(&self, url: &Url, mime: &str) -> bool { + pub fn matches(&self, url: &UrlBuf, mime: &str) -> bool { self.mime.as_ref().is_some_and(|p| p.match_mime(mime)) || self.url.as_ref().is_some_and(|p| p.match_url(url, mime == MIME_DIR)) } diff --git a/yazi-config/src/plugin/previewer.rs b/yazi-config/src/plugin/previewer.rs index 885835a1..2aff9340 100644 --- a/yazi-config/src/plugin/previewer.rs +++ b/yazi-config/src/plugin/previewer.rs @@ -1,5 +1,5 @@ use serde::Deserialize; -use yazi_shared::{MIME_DIR, event::Cmd, url::Url}; +use yazi_shared::{MIME_DIR, event::Cmd, url::UrlBuf}; use crate::Pattern; @@ -12,7 +12,7 @@ pub struct Previewer { impl Previewer { #[inline] - pub fn matches(&self, url: &Url, mime: &str) -> bool { + pub fn matches(&self, url: &UrlBuf, mime: &str) -> bool { self.mime.as_ref().is_some_and(|p| p.match_mime(mime)) || self.url.as_ref().is_some_and(|p| p.match_url(url, mime == MIME_DIR)) } diff --git a/yazi-config/src/plugin/spotter.rs b/yazi-config/src/plugin/spotter.rs index e00f9107..f8a1d3eb 100644 --- a/yazi-config/src/plugin/spotter.rs +++ b/yazi-config/src/plugin/spotter.rs @@ -1,5 +1,5 @@ use serde::Deserialize; -use yazi_shared::{MIME_DIR, event::Cmd, url::Url}; +use yazi_shared::{MIME_DIR, event::Cmd, url::UrlBuf}; use crate::Pattern; @@ -12,7 +12,7 @@ pub struct Spotter { impl Spotter { #[inline] - pub fn matches(&self, url: &Url, mime: &str) -> bool { + pub fn matches(&self, url: &UrlBuf, mime: &str) -> bool { self.mime.as_ref().is_some_and(|p| p.match_mime(mime)) || self.url.as_ref().is_some_and(|p| p.match_url(url, mime == MIME_DIR)) } diff --git a/yazi-config/src/popup/options.rs b/yazi-config/src/popup/options.rs index 3efa0ccc..039c3cb7 100644 --- a/yazi-config/src/popup/options.rs +++ b/yazi-config/src/popup/options.rs @@ -1,5 +1,5 @@ use ratatui::{text::{Line, Text}, widgets::{Paragraph, Wrap}}; -use yazi_shared::{IntoStringLossy, url::Url}; +use yazi_shared::{IntoStringLossy, url::UrlBuf}; use super::{Offset, Position}; use crate::YAZI; @@ -118,7 +118,7 @@ impl ConfirmCfg { } } - pub fn trash(urls: &[yazi_shared::url::Url]) -> Self { + pub fn trash(urls: &[yazi_shared::url::UrlBuf]) -> Self { Self::new( Self::replace_number(&YAZI.confirm.trash_title, urls.len()), YAZI.confirm.trash_position(), @@ -127,7 +127,7 @@ impl ConfirmCfg { ) } - pub fn delete(urls: &[yazi_shared::url::Url]) -> Self { + pub fn delete(urls: &[yazi_shared::url::UrlBuf]) -> Self { Self::new( Self::replace_number(&YAZI.confirm.delete_title, urls.len()), YAZI.confirm.delete_position(), @@ -136,7 +136,7 @@ impl ConfirmCfg { ) } - pub fn overwrite(url: &Url) -> Self { + pub fn overwrite(url: &UrlBuf) -> Self { Self::new( YAZI.confirm.overwrite_title.to_owned(), YAZI.confirm.overwrite_position(), diff --git a/yazi-config/src/preview/preview.rs b/yazi-config/src/preview/preview.rs index 55f7247a..8bfa6848 100644 --- a/yazi-config/src/preview/preview.rs +++ b/yazi-config/src/preview/preview.rs @@ -4,7 +4,7 @@ use anyhow::{Context, Result, bail}; use serde::{Deserialize, Serialize}; use yazi_codegen::DeserializeOver2; use yazi_fs::{Xdg, path::expand_url}; -use yazi_shared::{SStr, timestamp_us, url::Url}; +use yazi_shared::{SStr, timestamp_us, url::UrlBuf}; use super::PreviewWrap; @@ -53,7 +53,7 @@ impl Preview { self.cache_dir = if self.cache_dir.as_os_str().is_empty() { Xdg::cache_dir() - } else if let Some(p) = expand_url(Url::from(&self.cache_dir)).into_path() { + } else if let Some(p) = expand_url(UrlBuf::from(&self.cache_dir)).into_path() { p } else { bail!("[preview].cache_dir must be a path within local filesystem."); diff --git a/yazi-config/src/theme/theme.rs b/yazi-config/src/theme/theme.rs index b660ff02..b3a8369f 100644 --- a/yazi-config/src/theme/theme.rs +++ b/yazi-config/src/theme/theme.rs @@ -4,7 +4,7 @@ use anyhow::{Context, Result, anyhow, bail}; use serde::Deserialize; use yazi_codegen::{DeserializeOver1, DeserializeOver2}; use yazi_fs::{Xdg, ok_or_not_found, path::expand_url}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::{Filetype, Flavor, Icon}; use crate::Style; @@ -223,7 +223,7 @@ impl Theme { self.mgr.syntect_theme = self .flavor .syntect_path(light) - .or_else(|| expand_url(Url::from(&self.mgr.syntect_theme)).into_path()) + .or_else(|| expand_url(UrlBuf::from(&self.mgr.syntect_theme)).into_path()) .ok_or(anyhow!("[mgr].syntect_theme must be a path within local filesystem"))?; Ok(self) diff --git a/yazi-core/src/cmp/cmp.rs b/yazi-core/src/cmp/cmp.rs index 28f69c49..b4663fb0 100644 --- a/yazi-core/src/cmp/cmp.rs +++ b/yazi-core/src/cmp/cmp.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; use yazi_parser::cmp::CmpItem; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use yazi_widgets::Scrollable; #[derive(Default)] pub struct Cmp { - pub caches: HashMap>, + pub caches: HashMap>, pub cands: Vec, pub offset: usize, pub cursor: usize, diff --git a/yazi-core/src/mgr/linked.rs b/yazi-core/src/mgr/linked.rs index 6cb2685b..96da051c 100644 --- a/yazi-core/src/mgr/linked.rs +++ b/yazi-core/src/mgr/linked.rs @@ -1,12 +1,12 @@ use std::{collections::HashMap, iter, ops::{Deref, DerefMut}}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; #[derive(Default)] -pub struct Linked(HashMap /* from ==> to */); +pub struct Linked(HashMap /* from ==> to */); impl Deref for Linked { - type Target = HashMap; + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.0 } } @@ -16,7 +16,7 @@ impl DerefMut for Linked { } impl Linked { - pub fn from_dir<'a, 'b>(&'a self, url: &'b Url) -> Box + 'b> + pub fn from_dir<'a, 'b>(&'a self, url: &'b UrlBuf) -> Box + 'b> where 'a: 'b, { @@ -29,7 +29,7 @@ impl Linked { } } - pub fn from_file(&self, url: &Url) -> Vec { + pub fn from_file(&self, url: &UrlBuf) -> Vec { if url.scheme.is_virtual() { vec![] } else if let Some((parent, urn)) = url.pair() { diff --git a/yazi-core/src/mgr/mgr.rs b/yazi-core/src/mgr/mgr.rs index 4fd97e06..15761fbd 100644 --- a/yazi-core/src/mgr/mgr.rs +++ b/yazi-core/src/mgr/mgr.rs @@ -1,7 +1,7 @@ use ratatui::layout::Rect; use yazi_adapter::Dimension; use yazi_config::popup::{Origin, Position}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::{Mimetype, Tabs, Watcher, Yanked}; use crate::tab::{Folder, Tab}; @@ -38,7 +38,7 @@ impl Mgr { impl Mgr { #[inline] - pub fn cwd(&self) -> &Url { self.active().cwd() } + pub fn cwd(&self) -> &UrlBuf { self.active().cwd() } #[inline] pub fn active(&self) -> &Tab { self.tabs.active() } diff --git a/yazi-core/src/mgr/mimetype.rs b/yazi-core/src/mgr/mimetype.rs index a83d6e9c..ad689a19 100644 --- a/yazi-core/src/mgr/mimetype.rs +++ b/yazi-core/src/mgr/mimetype.rs @@ -1,19 +1,19 @@ use std::{borrow::Cow, collections::HashMap}; use yazi_fs::File; -use yazi_shared::{MIME_DIR, SStr, url::{CovUrl, Url}}; +use yazi_shared::{MIME_DIR, SStr, url::{UrlBuf, UrlCov}}; #[derive(Default)] -pub struct Mimetype(HashMap); +pub struct Mimetype(HashMap); impl Mimetype { #[inline] - pub fn by_url(&self, url: &Url) -> Option<&str> { - self.0.get(CovUrl::new(url)).map(|s| s.as_str()) + pub fn by_url(&self, url: &UrlBuf) -> Option<&str> { + self.0.get(UrlCov::new(url)).map(|s| s.as_str()) } #[inline] - pub fn by_url_owned(&self, url: &Url) -> Option { + pub fn by_url_owned(&self, url: &UrlBuf) -> Option { self.by_url(url).map(|s| Cow::Owned(s.to_owned())) } @@ -28,10 +28,10 @@ impl Mimetype { } #[inline] - pub fn contains(&self, url: &Url) -> bool { self.0.contains_key(CovUrl::new(url)) } + pub fn contains(&self, url: &UrlBuf) -> bool { self.0.contains_key(UrlCov::new(url)) } #[inline] - pub fn extend(&mut self, iter: impl IntoIterator) { - self.0.extend(iter.into_iter().map(|(u, m)| (CovUrl(u), m))); + pub fn extend(&mut self, iter: impl IntoIterator) { + self.0.extend(iter.into_iter().map(|(u, m)| (UrlCov(u), m))); } } diff --git a/yazi-core/src/mgr/watcher.rs b/yazi-core/src/mgr/watcher.rs index d2da0af8..63d69e74 100644 --- a/yazi-core/src/mgr/watcher.rs +++ b/yazi-core/src/mgr/watcher.rs @@ -8,17 +8,17 @@ use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use tracing::error; use yazi_fs::{File, Files, FilesOp, cha::Cha, provider, realname_unchecked}; use yazi_proxy::WATCHER; -use yazi_shared::{RoCell, url::Url}; +use yazi_shared::{RoCell, url::UrlBuf}; use super::Linked; use crate::tab::Folder; -pub(crate) static WATCHED: RoCell>> = RoCell::new(); +pub(crate) static WATCHED: RoCell>> = RoCell::new(); pub static LINKED: RoCell> = RoCell::new(); pub struct Watcher { - in_tx: watch::Sender>, - out_tx: mpsc::UnboundedSender, + in_tx: watch::Sender>, + out_tx: mpsc::UnboundedSender, } // FIXME: VFS @@ -33,7 +33,7 @@ impl Watcher { if event.kind.is_access() { return; } - Self::push_files_impl(&out_tx_, event.paths.into_iter().map(Url::from)); + Self::push_files_impl(&out_tx_, event.paths.into_iter().map(UrlBuf::from)); }; let config = notify::Config::default().with_poll_interval(Duration::from_millis(500)); @@ -52,15 +52,15 @@ impl Watcher { Self { in_tx, out_tx } } - pub fn watch<'a>(&mut self, it: impl Iterator) { + pub fn watch<'a>(&mut self, it: impl Iterator) { self.in_tx.send(it.filter(|u| u.is_regular()).cloned().collect()).ok(); } - pub fn push_files(&self, urls: Vec) { + pub fn push_files(&self, urls: Vec) { Self::push_files_impl(&self.out_tx, urls.into_iter()); } - fn push_files_impl(out_tx: &mpsc::UnboundedSender, urls: impl Iterator) { + fn push_files_impl(out_tx: &mpsc::UnboundedSender, urls: impl Iterator) { let (mut parents, watched) = (HashSet::new(), WATCHED.read()); for u in urls { let Some(p) = u.parent_url() else { continue }; @@ -77,7 +77,7 @@ impl Watcher { // TODO: performance improvement pub fn trigger_dirs(&self, folders: &[&Folder]) { - async fn go(cwd: Url, cha: Cha) { + async fn go(cwd: UrlBuf, cha: Cha) { let Some(cha) = Files::assert_stale(&cwd, cha).await else { return }; match Files::from_dir_bulk(&cwd).await { @@ -98,7 +98,7 @@ impl Watcher { } async fn fan_in( - mut rx: watch::Receiver>, + mut rx: watch::Receiver>, mut watcher: impl notify::Watcher + Send + 'static, ) { loop { @@ -119,7 +119,7 @@ impl Watcher { } } - async fn fan_out(rx: UnboundedReceiver) { + async fn fan_out(rx: UnboundedReceiver) { // TODO: revert this once a new notification is implemented let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(250)); pin!(rx); @@ -154,7 +154,11 @@ impl Watcher { } } - async fn sync_watched(mut watcher: W, to_unwatch: HashSet, to_watch: HashSet) -> W + async fn sync_watched( + mut watcher: W, + to_unwatch: HashSet, + to_watch: HashSet, + ) -> W where W: notify::Watcher + Send + 'static, { @@ -192,7 +196,7 @@ impl Watcher { linked.keys().cloned().collect() }; - async fn go(todo: HashSet) { + async fn go(todo: HashSet) { for from in todo { let Ok(to) = provider::canonicalize(&from).await else { continue }; diff --git a/yazi-core/src/mgr/yanked.rs b/yazi-core/src/mgr/yanked.rs index e585419b..bc11d424 100644 --- a/yazi-core/src/mgr/yanked.rs +++ b/yazi-core/src/mgr/yanked.rs @@ -3,28 +3,28 @@ use std::{collections::HashSet, ops::Deref}; use yazi_dds::Pubsub; use yazi_fs::FilesOp; use yazi_macro::err; -use yazi_shared::url::{CovUrl, Url}; +use yazi_shared::url::{UrlBuf, UrlCov}; #[derive(Debug, Default)] pub struct Yanked { pub cut: bool, - urls: HashSet, + urls: HashSet, version: u64, revision: u64, } impl Deref for Yanked { - type Target = HashSet; + type Target = HashSet; fn deref(&self) -> &Self::Target { &self.urls } } impl Yanked { - pub fn new(cut: bool, urls: HashSet) -> Self { Self { cut, urls, ..Default::default() } } + pub fn new(cut: bool, urls: HashSet) -> Self { Self { cut, urls, ..Default::default() } } - pub fn remove(&mut self, url: &Url) { - if self.urls.remove(CovUrl::new(url)) { + pub fn remove(&mut self, url: &UrlBuf) { + if self.urls.remove(UrlCov::new(url)) { self.revision += 1; } } @@ -39,9 +39,9 @@ impl Yanked { } #[inline] - pub fn contains(&self, url: impl AsRef) -> bool { self.urls.contains(CovUrl::new(&url)) } + pub fn contains(&self, url: impl AsRef) -> bool { self.urls.contains(UrlCov::new(&url)) } - pub fn contains_in(&self, dir: &Url) -> bool { + pub fn contains_in(&self, dir: &UrlBuf) -> bool { self.urls.iter().any(|u| { let mut it = u.components(); it.next_back().is_some() @@ -60,7 +60,7 @@ impl Yanked { if !addition.is_empty() { let old = self.urls.len(); - self.urls.extend(addition.into_iter().map(CovUrl)); + self.urls.extend(addition.into_iter().map(UrlCov)); self.revision += (old != self.urls.len()) as u64; } } diff --git a/yazi-core/src/spot/spot.rs b/yazi-core/src/spot/spot.rs index 8cc980c6..9afe589d 100644 --- a/yazi-core/src/spot/spot.rs +++ b/yazi-core/src/spot/spot.rs @@ -4,7 +4,7 @@ use yazi_fs::File; use yazi_macro::render; use yazi_parser::mgr::SpotLock; use yazi_plugin::isolate; -use yazi_shared::{SStr, url::Url}; +use yazi_shared::{SStr, url::UrlBuf}; #[derive(Default)] pub struct Spot { @@ -43,7 +43,7 @@ impl Spot { } #[inline] - pub fn same_url(&self, url: &Url) -> bool { self.lock.as_ref().is_some_and(|l| *url == l.url) } + pub fn same_url(&self, url: &UrlBuf) -> bool { self.lock.as_ref().is_some_and(|l| *url == l.url) } #[inline] pub fn same_file(&self, file: &File, mime: &str) -> bool { diff --git a/yazi-core/src/tab/finder.rs b/yazi-core/src/tab/finder.rs index 71be5df4..6ecf9a0c 100644 --- a/yazi-core/src/tab/finder.rs +++ b/yazi-core/src/tab/finder.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use yazi_fs::{Files, Filter, FilterCase}; -use yazi_shared::url::{Url, Urn, UrnBuf}; +use yazi_shared::url::{UrlBuf, Urn, UrnBuf}; use crate::tab::Folder; @@ -14,7 +14,7 @@ pub struct Finder { #[derive(Default)] struct FinderLock { - cwd: Url, + cwd: UrlBuf, revision: u64, } diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index a038b83d..b2e66239 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -6,11 +6,11 @@ use yazi_fs::{File, Files, FilesOp, FolderStage, cha::Cha}; use yazi_macro::err; use yazi_parser::Step; use yazi_proxy::MgrProxy; -use yazi_shared::{Id, url::{Url, Urn, UrnBuf}}; +use yazi_shared::{Id, url::{UrlBuf, Urn, UrnBuf}}; use yazi_widgets::Scrollable; pub struct Folder { - pub url: Url, + pub url: UrlBuf, pub cha: Cha, pub files: Files, pub stage: FolderStage, @@ -37,8 +37,8 @@ impl Default for Folder { } } -impl From<&Url> for Folder { - fn from(url: &Url) -> Self { Self { url: url.clone(), ..Default::default() } } +impl From<&UrlBuf> for Folder { + fn from(url: &UrlBuf) -> Self { Self { url: url.clone(), ..Default::default() } } } impl Folder { diff --git a/yazi-core/src/tab/history.rs b/yazi-core/src/tab/history.rs index 699715d0..e4074102 100644 --- a/yazi-core/src/tab/history.rs +++ b/yazi-core/src/tab/history.rs @@ -1,14 +1,14 @@ use std::{collections::HashMap, ops::{Deref, DerefMut}}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Folder; #[derive(Default)] -pub struct History(HashMap); +pub struct History(HashMap); impl Deref for History { - type Target = HashMap; + type Target = HashMap; #[inline] fn deref(&self) -> &Self::Target { &self.0 } @@ -21,7 +21,7 @@ impl DerefMut for History { impl History { #[inline] - pub fn remove_or(&mut self, url: &Url) -> Folder { + pub fn remove_or(&mut self, url: &UrlBuf) -> Folder { self.0.remove(url).unwrap_or_else(|| Folder::from(url)) } } diff --git a/yazi-core/src/tab/preview.rs b/yazi-core/src/tab/preview.rs index 6f67fabf..b638aafc 100644 --- a/yazi-core/src/tab/preview.rs +++ b/yazi-core/src/tab/preview.rs @@ -9,7 +9,7 @@ use yazi_fs::{File, Files, FilesOp, cha::Cha}; use yazi_macro::render; use yazi_parser::mgr::PreviewLock; use yazi_plugin::{external::Highlighter, isolate}; -use yazi_shared::{MIME_DIR, SStr, url::Url}; +use yazi_shared::{MIME_DIR, SStr, url::UrlBuf}; #[derive(Default)] pub struct Preview { @@ -88,7 +88,7 @@ impl Preview { } #[inline] - pub fn same_url(&self, url: &Url) -> bool { matches!(&self.lock, Some(l) if l.url == *url) } + pub fn same_url(&self, url: &UrlBuf) -> bool { matches!(&self.lock, Some(l) if l.url == *url) } #[inline] pub fn same_file(&self, file: &File, mime: &str) -> bool { diff --git a/yazi-core/src/tab/selected.rs b/yazi-core/src/tab/selected.rs index 24d1b9b4..ae74d1d2 100644 --- a/yazi-core/src/tab/selected.rs +++ b/yazi-core/src/tab/selected.rs @@ -2,12 +2,12 @@ use std::{collections::HashMap, ops::Deref}; use indexmap::IndexMap; use yazi_fs::FilesOp; -use yazi_shared::{timestamp_us, url::{CovUrl, Url}}; +use yazi_shared::{timestamp_us, url::{UrlBuf, UrlCov}}; #[derive(Default)] pub struct Selected { - inner: IndexMap, - parents: HashMap, + inner: IndexMap, + parents: HashMap, } impl Selected { @@ -18,17 +18,17 @@ impl Selected { pub fn is_empty(&self) -> bool { self.inner.is_empty() } #[inline] - pub fn values(&self) -> impl Iterator { self.inner.keys().map(Deref::deref) } + pub fn values(&self) -> impl Iterator { self.inner.keys().map(Deref::deref) } #[inline] - pub fn contains(&self, url: impl AsRef) -> bool { - self.inner.contains_key(CovUrl::new(&url)) + pub fn contains(&self, url: impl AsRef) -> bool { + self.inner.contains_key(UrlCov::new(&url)) } #[inline] - pub fn add(&mut self, url: &Url) -> bool { self.add_same(&[url]) == 1 } + pub fn add(&mut self, url: &UrlBuf) -> bool { self.add_same(&[url]) == 1 } - pub fn add_many(&mut self, urls: &[impl AsRef]) -> usize { + pub fn add_many(&mut self, urls: &[impl AsRef]) -> usize { let mut grouped: HashMap<_, Vec<_>> = Default::default(); for u in urls { if let Some(p) = u.as_ref().parent_url() { @@ -38,10 +38,10 @@ impl Selected { grouped.into_values().map(|v| self.add_same(&v)).sum() } - fn add_same(&mut self, urls: &[impl AsRef]) -> usize { + fn add_same(&mut self, urls: &[impl AsRef]) -> usize { // If it has appeared as a parent let urls: Vec<_> = - urls.iter().map(CovUrl::new).filter(|&u| !self.parents.contains_key(u)).collect(); + urls.iter().map(UrlCov::new).filter(|&u| !self.parents.contains_key(u)).collect(); if urls.is_empty() { return 0; } @@ -68,9 +68,9 @@ impl Selected { } #[inline] - pub fn remove(&mut self, url: &Url) -> bool { self.remove_same(&[url]) == 1 } + pub fn remove(&mut self, url: &UrlBuf) -> bool { self.remove_same(&[url]) == 1 } - pub fn remove_many(&mut self, urls: &[impl AsRef]) -> usize { + pub fn remove_many(&mut self, urls: &[impl AsRef]) -> usize { let mut grouped: HashMap<_, Vec<_>> = Default::default(); for u in urls { if let Some(p) = u.as_ref().parent_url() { @@ -86,13 +86,13 @@ impl Selected { affected } - fn remove_same(&mut self, urls: &[impl AsRef]) -> usize { - let count = urls.iter().filter_map(|u| self.inner.swap_remove(CovUrl::new(u))).count(); + fn remove_same(&mut self, urls: &[impl AsRef]) -> usize { + let count = urls.iter().filter_map(|u| self.inner.swap_remove(UrlCov::new(u))).count(); if count == 0 { return 0; } - let mut parent = CovUrl::new(&urls[0]).parent_url(); + let mut parent = UrlCov::new(&urls[0]).parent_url(); while let Some(u) = parent { let n = self.parents.get_mut(&u).unwrap(); @@ -126,7 +126,7 @@ impl Selected { mod tests { use super::*; - fn url(s: &str) -> Url { s.parse().unwrap() } + fn url(s: &str) -> UrlBuf { s.parse().unwrap() } #[test] fn test_insert_non_conflicting() { @@ -196,7 +196,7 @@ mod tests { fn insert_many_empty_urls_list() { let mut s = Selected::default(); - assert_eq!(0, s.add_same(&[] as &[&Url])); + assert_eq!(0, s.add_same(&[] as &[&UrlBuf])); } #[test] diff --git a/yazi-core/src/tab/tab.rs b/yazi-core/src/tab/tab.rs index e0e16df3..60fc1bd9 100644 --- a/yazi-core/src/tab/tab.rs +++ b/yazi-core/src/tab/tab.rs @@ -6,7 +6,7 @@ use tokio::task::JoinHandle; use yazi_adapter::Dimension; use yazi_config::{LAYOUT, popup::{Origin, Position}}; use yazi_fs::File; -use yazi_shared::{Id, Ids, url::Url}; +use yazi_shared::{Id, Ids, url::UrlBuf}; use super::{Backstack, Finder, Folder, History, Mode, Preference, Preview}; use crate::{spot::Spot, tab::Selected}; @@ -18,7 +18,7 @@ pub struct Tab { pub current: Folder, pub parent: Option, - pub backstack: Backstack, + pub backstack: Backstack, pub history: History, pub selected: Selected, @@ -61,7 +61,7 @@ impl Tab { impl Tab { // --- Current #[inline] - pub fn cwd(&self) -> &Url { &self.current.url } + pub fn cwd(&self) -> &UrlBuf { &self.current.url } #[inline] pub fn hovered(&self) -> Option<&File> { self.current.hovered() } @@ -87,7 +87,7 @@ impl Tab { } } - pub fn selected_or_hovered(&self) -> Box + '_> { + pub fn selected_or_hovered(&self) -> Box + '_> { if self.selected.is_empty() { Box::new(self.hovered().map(|h| &h.url).into_iter()) } else { @@ -95,7 +95,7 @@ impl Tab { } } - pub fn hovered_and_selected(&self) -> Box + '_> { + pub fn hovered_and_selected(&self) -> Box + '_> { let Some(h) = self.hovered() else { return Box::new(iter::empty()) }; if self.selected.is_empty() { Box::new([&h.url, &h.url].into_iter()) diff --git a/yazi-core/src/tasks/file.rs b/yazi-core/src/tasks/file.rs index 27441aad..b2fb9375 100644 --- a/yazi-core/src/tasks/file.rs +++ b/yazi-core/src/tasks/file.rs @@ -1,12 +1,12 @@ use std::collections::HashSet; use tracing::debug; -use yazi_shared::url::{CovUrl, Url}; +use yazi_shared::url::{UrlBuf, UrlCov}; use super::Tasks; impl Tasks { - pub fn file_cut(&self, src: &[&CovUrl], dest: &Url, force: bool) { + pub fn file_cut(&self, src: &[&UrlCov], dest: &UrlBuf, force: bool) { for &u in src { let to = dest.join(u.file_name().unwrap()); if force && *u == to { @@ -17,7 +17,7 @@ impl Tasks { } } - pub fn file_copy(&self, src: &[&CovUrl], dest: &Url, force: bool, follow: bool) { + pub fn file_copy(&self, src: &[&UrlCov], dest: &UrlBuf, force: bool, follow: bool) { for &u in src { let to = dest.join(u.file_name().unwrap()); if force && *u == to { @@ -28,7 +28,7 @@ impl Tasks { } } - pub fn file_link(&self, src: &HashSet, dest: &Url, relative: bool, force: bool) { + pub fn file_link(&self, src: &HashSet, dest: &UrlBuf, relative: bool, force: bool) { for u in src { let to = dest.join(u.file_name().unwrap()); if force && *u == to { @@ -39,7 +39,7 @@ impl Tasks { } } - pub fn file_hardlink(&self, src: &HashSet, dest: &Url, force: bool, follow: bool) { + pub fn file_hardlink(&self, src: &HashSet, dest: &UrlBuf, force: bool, follow: bool) { for u in src { let to = dest.join(u.file_name().unwrap()); if force && *u == to { @@ -50,7 +50,7 @@ impl Tasks { } } - pub fn file_remove(&self, targets: Vec, permanently: bool) { + pub fn file_remove(&self, targets: Vec, permanently: bool) { for u in targets { if permanently { self.scheduler.file_delete(u); diff --git a/yazi-core/src/tasks/process.rs b/yazi-core/src/tasks/process.rs index a79930f1..ac02b48c 100644 --- a/yazi-core/src/tasks/process.rs +++ b/yazi-core/src/tasks/process.rs @@ -2,12 +2,12 @@ use std::{borrow::Cow, collections::HashMap, ffi::OsString, mem}; use yazi_config::{YAZI, opener::OpenerRule}; use yazi_parser::tasks::ProcessExecOpt; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Tasks; impl Tasks { - pub fn process_from_files(&self, cwd: Url, hovered: Url, targets: Vec<(Url, &str)>) { + pub fn process_from_files(&self, cwd: UrlBuf, hovered: UrlBuf, targets: Vec<(UrlBuf, &str)>) { let mut openers = HashMap::new(); for (url, mime) in targets { if let Some(opener) = YAZI.opener.first(YAZI.open.all(&url, mime)) { @@ -25,7 +25,7 @@ impl Tasks { pub fn process_from_opener( &self, - cwd: Url, + cwd: UrlBuf, opener: Cow<'static, OpenerRule>, mut args: Vec, ) { diff --git a/yazi-dds/src/ember/bulk.rs b/yazi-dds/src/ember/bulk.rs index 7a30ade9..2edae315 100644 --- a/yazi-dds/src/ember/bulk.rs +++ b/yazi-dds/src/ember/bulk.rs @@ -2,19 +2,19 @@ use std::{borrow::Cow, collections::HashMap}; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberBulk<'a> { - pub changes: HashMap, Cow<'a, Url>>, + pub changes: HashMap, Cow<'a, UrlBuf>>, } impl<'a> EmberBulk<'a> { pub fn borrowed(changes: I) -> Ember<'a> where - I: Iterator, + I: Iterator, { Self { changes: changes.map(|(from, to)| (from.into(), to.into())).collect() }.into() } @@ -23,7 +23,7 @@ impl<'a> EmberBulk<'a> { impl EmberBulk<'static> { pub fn owned<'a, I>(changes: I) -> Ember<'static> where - I: Iterator, + I: Iterator, { Self { changes: changes.map(|(from, to)| (from.clone().into(), to.clone().into())).collect() } .into() diff --git a/yazi-dds/src/ember/cd.rs b/yazi-dds/src/ember/cd.rs index 54b306b3..5bd413ec 100644 --- a/yazi-dds/src/ember/cd.rs +++ b/yazi-dds/src/ember/cd.rs @@ -2,26 +2,26 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberCd<'a> { pub tab: Id, - pub url: Cow<'a, Url>, + pub url: Cow<'a, UrlBuf>, #[serde(skip)] dummy: bool, } impl<'a> EmberCd<'a> { - pub fn borrowed(tab: Id, url: &'a Url) -> Ember<'a> { + pub fn borrowed(tab: Id, url: &'a UrlBuf) -> Ember<'a> { Self { tab, url: url.into(), dummy: false }.into() } } impl EmberCd<'static> { - pub fn owned(tab: Id, _: &Url) -> Ember<'static> { + pub fn owned(tab: Id, _: &UrlBuf) -> Ember<'static> { Self { tab, url: Default::default(), dummy: true }.into() } } diff --git a/yazi-dds/src/ember/delete.rs b/yazi-dds/src/ember/delete.rs index 6d85e809..fcbe4692 100644 --- a/yazi-dds/src/ember/delete.rs +++ b/yazi-dds/src/ember/delete.rs @@ -2,21 +2,21 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberDelete<'a> { - pub urls: Cow<'a, Vec>, + pub urls: Cow<'a, Vec>, } impl<'a> EmberDelete<'a> { - pub fn borrowed(urls: &'a Vec) -> Ember<'a> { Self { urls: Cow::Borrowed(urls) }.into() } + pub fn borrowed(urls: &'a Vec) -> Ember<'a> { Self { urls: Cow::Borrowed(urls) }.into() } } impl EmberDelete<'static> { - pub fn owned(urls: Vec) -> Ember<'static> { Self { urls: Cow::Owned(urls) }.into() } + pub fn owned(urls: Vec) -> Ember<'static> { Self { urls: Cow::Owned(urls) }.into() } } impl<'a> From> for Ember<'a> { diff --git a/yazi-dds/src/ember/hover.rs b/yazi-dds/src/ember/hover.rs index 43acc4ab..48b1432f 100644 --- a/yazi-dds/src/ember/hover.rs +++ b/yazi-dds/src/ember/hover.rs @@ -2,24 +2,24 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberHover<'a> { pub tab: Id, - pub url: Option>, + pub url: Option>, } impl<'a> EmberHover<'a> { - pub fn borrowed(tab: Id, url: Option<&'a Url>) -> Ember<'a> { + pub fn borrowed(tab: Id, url: Option<&'a UrlBuf>) -> Ember<'a> { Self { tab, url: url.map(Into::into) }.into() } } impl EmberHover<'static> { - pub fn owned(tab: Id, _: Option<&Url>) -> Ember<'static> { Self { tab, url: None }.into() } + pub fn owned(tab: Id, _: Option<&UrlBuf>) -> Ember<'static> { Self { tab, url: None }.into() } } impl<'a> From> for Ember<'a> { diff --git a/yazi-dds/src/ember/load.rs b/yazi-dds/src/ember/load.rs index 76ce33b3..f1196e67 100644 --- a/yazi-dds/src/ember/load.rs +++ b/yazi-dds/src/ember/load.rs @@ -3,25 +3,25 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; use yazi_fs::FolderStage; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberLoad<'a> { pub tab: Id, - pub url: Cow<'a, Url>, + pub url: Cow<'a, UrlBuf>, pub stage: FolderStage, } impl<'a> EmberLoad<'a> { - pub fn borrowed(tab: Id, url: &'a Url, stage: FolderStage) -> Ember<'a> { + pub fn borrowed(tab: Id, url: &'a UrlBuf, stage: FolderStage) -> Ember<'a> { Self { tab, url: url.into(), stage }.into() } } impl EmberLoad<'static> { - pub fn owned(tab: Id, url: &Url, stage: FolderStage) -> Ember<'static> { + pub fn owned(tab: Id, url: &UrlBuf, stage: FolderStage) -> Ember<'static> { Self { tab, url: url.clone().into(), stage }.into() } } diff --git a/yazi-dds/src/ember/move.rs b/yazi-dds/src/ember/move.rs index 7f0afcb0..a08d7354 100644 --- a/yazi-dds/src/ember/move.rs +++ b/yazi-dds/src/ember/move.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Ember; @@ -36,8 +36,8 @@ impl IntoLua for EmberMove<'_> { // --- Item #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BodyMoveItem { - pub from: Url, - pub to: Url, + pub from: UrlBuf, + pub to: UrlBuf, } impl IntoLua for BodyMoveItem { diff --git a/yazi-dds/src/ember/rename.rs b/yazi-dds/src/ember/rename.rs index cbe580e7..6fa3f6c7 100644 --- a/yazi-dds/src/ember/rename.rs +++ b/yazi-dds/src/ember/rename.rs @@ -2,25 +2,25 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberRename<'a> { pub tab: Id, - pub from: Cow<'a, Url>, - pub to: Cow<'a, Url>, + pub from: Cow<'a, UrlBuf>, + pub to: Cow<'a, UrlBuf>, } impl<'a> EmberRename<'a> { - pub fn borrowed(tab: Id, from: &'a Url, to: &'a Url) -> Ember<'a> { + pub fn borrowed(tab: Id, from: &'a UrlBuf, to: &'a UrlBuf) -> Ember<'a> { Self { tab, from: from.into(), to: to.into() }.into() } } impl EmberRename<'static> { - pub fn owned(tab: Id, from: &Url, to: &Url) -> Ember<'static> { + pub fn owned(tab: Id, from: &UrlBuf, to: &UrlBuf) -> Ember<'static> { Self { tab, from: from.clone().into(), to: to.clone().into() }.into() } } diff --git a/yazi-dds/src/ember/trash.rs b/yazi-dds/src/ember/trash.rs index e95f90d0..c39e548e 100644 --- a/yazi-dds/src/ember/trash.rs +++ b/yazi-dds/src/ember/trash.rs @@ -2,21 +2,21 @@ use std::borrow::Cow; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::Ember; #[derive(Debug, Serialize, Deserialize)] pub struct EmberTrash<'a> { - pub urls: Cow<'a, Vec>, + pub urls: Cow<'a, Vec>, } impl<'a> EmberTrash<'a> { - pub fn borrowed(urls: &'a Vec) -> Ember<'a> { Self { urls: Cow::Borrowed(urls) }.into() } + pub fn borrowed(urls: &'a Vec) -> Ember<'a> { Self { urls: Cow::Borrowed(urls) }.into() } } impl EmberTrash<'static> { - pub fn owned(urls: Vec) -> Ember<'static> { Self { urls: Cow::Owned(urls) }.into() } + pub fn owned(urls: Vec) -> Ember<'static> { Self { urls: Cow::Owned(urls) }.into() } } impl<'a> From> for Ember<'a> { diff --git a/yazi-dds/src/ember/yank.rs b/yazi-dds/src/ember/yank.rs index be2eff88..c412a57a 100644 --- a/yazi-dds/src/ember/yank.rs +++ b/yazi-dds/src/ember/yank.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashSet}; use mlua::{IntoLua, Lua, Value}; use serde::{Deserialize, Serialize}; use yazi_parser::mgr::UpdateYankedOpt; -use yazi_shared::url::CovUrl; +use yazi_shared::url::UrlCov; use super::Ember; @@ -11,13 +11,13 @@ use super::Ember; pub struct EmberYank<'a>(UpdateYankedOpt<'a>); impl<'a> EmberYank<'a> { - pub fn borrowed(cut: bool, urls: &'a HashSet) -> Ember<'a> { + pub fn borrowed(cut: bool, urls: &'a HashSet) -> Ember<'a> { Self(UpdateYankedOpt { cut, urls: Cow::Borrowed(urls) }).into() } } impl EmberYank<'static> { - pub fn owned(cut: bool, _: &HashSet) -> Ember<'static> { + pub fn owned(cut: bool, _: &HashSet) -> Ember<'static> { Self(UpdateYankedOpt { cut, urls: Default::default() }).into() } } diff --git a/yazi-dds/src/pubsub.rs b/yazi-dds/src/pubsub.rs index 4dfe0214..f907502a 100644 --- a/yazi-dds/src/pubsub.rs +++ b/yazi-dds/src/pubsub.rs @@ -5,7 +5,7 @@ use mlua::Function; use parking_lot::RwLock; use yazi_boot::BOOT; use yazi_fs::FolderStage; -use yazi_shared::{Id, RoCell, url::{CovUrl, Url}}; +use yazi_shared::{Id, RoCell, url::{UrlBuf, UrlCov}}; use crate::{Client, ID, PEERS, ember::{BodyMoveItem, Ember, EmberBulk, EmberHi}}; @@ -124,7 +124,7 @@ impl Pubsub { pub fn pub_after_bulk<'a, I>(changes: I) -> Result<()> where - I: Iterator + Clone, + I: Iterator + Clone, { if BOOT.local_events.contains("bulk") { EmberBulk::borrowed(changes.clone()).with_receiver(*ID).flush()?; @@ -149,21 +149,21 @@ impl Pubsub { impl Pubsub { pub_after!(tab(idx: Id), (idx)); - pub_after!(cd(tab: Id, url: &Url), (tab, url)); + pub_after!(cd(tab: Id, url: &UrlBuf), (tab, url)); - pub_after!(load(tab: Id, url: &Url, stage: FolderStage), (tab, url, stage)); + pub_after!(load(tab: Id, url: &UrlBuf, stage: FolderStage), (tab, url, stage)); - pub_after!(hover(tab: Id, url: Option<&Url>), (tab, url)); + pub_after!(hover(tab: Id, url: Option<&UrlBuf>), (tab, url)); - pub_after!(rename(tab: Id, from: &Url, to: &Url), (tab, from, to)); + pub_after!(rename(tab: Id, from: &UrlBuf, to: &UrlBuf), (tab, from, to)); - pub_after!(@yank(cut: bool, urls: &HashSet), (cut, urls)); + pub_after!(@yank(cut: bool, urls: &HashSet), (cut, urls)); pub_after!(move(items: Vec), (&items), (items)); - pub_after!(trash(urls: Vec), (&urls), (urls)); + pub_after!(trash(urls: Vec), (&urls), (urls)); - pub_after!(delete(urls: Vec), (&urls), (urls)); + pub_after!(delete(urls: Vec), (&urls), (urls)); pub_after!(mount(), ()); } diff --git a/yazi-dds/src/pump.rs b/yazi-dds/src/pump.rs index 9a1f4826..e623a062 100644 --- a/yazi-dds/src/pump.rs +++ b/yazi-dds/src/pump.rs @@ -5,34 +5,34 @@ use tokio::{pin, select, sync::mpsc}; use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream}; use tokio_util::sync::CancellationToken; use yazi_macro::err; -use yazi_shared::{RoCell, url::Url}; +use yazi_shared::{RoCell, url::UrlBuf}; use crate::{Pubsub, ember::BodyMoveItem}; static CT: RoCell = RoCell::new(); static MOVE_TX: Mutex>> = Mutex::new(None); -static TRASH_TX: Mutex>> = Mutex::new(None); -static DELETE_TX: Mutex>> = Mutex::new(None); +static TRASH_TX: Mutex>> = Mutex::new(None); +static DELETE_TX: Mutex>> = Mutex::new(None); pub struct Pump; impl Pump { #[inline] - pub fn push_move(from: Url, to: Url) { + pub fn push_move(from: UrlBuf, to: UrlBuf) { if let Some(tx) = &*MOVE_TX.lock() { tx.send(BodyMoveItem { from, to }).ok(); } } #[inline] - pub fn push_trash(target: Url) { + pub fn push_trash(target: UrlBuf) { if let Some(tx) = &*TRASH_TX.lock() { tx.send(target).ok(); } } #[inline] - pub fn push_delete(target: Url) { + pub fn push_delete(target: UrlBuf) { if let Some(tx) = &*DELETE_TX.lock() { tx.send(target).ok(); } diff --git a/yazi-fs/src/calculator.rs b/yazi-fs/src/calculator.rs index 75d33c67..6dd26c7f 100644 --- a/yazi-fs/src/calculator.rs +++ b/yazi-fs/src/calculator.rs @@ -1,11 +1,11 @@ use std::{collections::VecDeque, future::poll_fn, io, mem, pin::Pin, task::{Poll, ready}, time::{Duration, Instant}}; use tokio::task::JoinHandle; -use yazi_shared::{Either, url::Url}; +use yazi_shared::{Either, url::UrlBuf}; use crate::provider::{self, ReadDirSync}; -type Task = Either; +type Task = Either; pub enum SizeCalculator { Idle((VecDeque, Option)), @@ -13,7 +13,7 @@ pub enum SizeCalculator { } impl SizeCalculator { - pub async fn new(url: &Url) -> io::Result { + pub async fn new(url: &UrlBuf) -> io::Result { let u = url.to_owned(); tokio::task::spawn_blocking(move || { let meta = provider::symlink_metadata_sync(&u)?; @@ -28,7 +28,7 @@ impl SizeCalculator { .await? } - pub async fn total(url: &Url) -> io::Result { + pub async fn total(url: &UrlBuf) -> io::Result { let mut it = Self::new(url).await?; let mut total = 0; while let Some(n) = it.next().await? { @@ -63,7 +63,7 @@ impl SizeCalculator { .await } - fn next_chunk(buf: &mut VecDeque>) -> Option { + fn next_chunk(buf: &mut VecDeque>) -> Option { let (mut i, mut size, now) = (0, 0, Instant::now()); macro_rules! pop_and_continue { () => {{ diff --git a/yazi-fs/src/cha/cha.rs b/yazi-fs/src/cha/cha.rs index 7a9535e1..7eaa0f4b 100644 --- a/yazi-fs/src/cha/cha.rs +++ b/yazi-fs/src/cha/cha.rs @@ -1,7 +1,7 @@ use std::{fs::{FileType, Metadata}, time::SystemTime}; use yazi_macro::{unix_either, win_either}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use super::ChaKind; use crate::provider; @@ -53,16 +53,16 @@ impl Default for Cha { impl Cha { #[inline] - pub fn new(url: &Url, meta: Metadata) -> Self { + pub fn new(url: &UrlBuf, meta: Metadata) -> Self { Self::from_just_meta(&meta).attach(ChaKind::hidden(url, &meta)) } #[inline] - pub async fn from_url(url: &Url) -> std::io::Result { + pub async fn from_url(url: &UrlBuf) -> std::io::Result { Ok(Self::from_follow(url, provider::symlink_metadata(url).await?).await) } - pub async fn from_follow(url: &Url, mut meta: Metadata) -> Self { + pub async fn from_follow(url: &UrlBuf, mut meta: Metadata) -> Self { let mut attached = ChaKind::hidden(url, &meta); if meta.is_symlink() { attached |= ChaKind::LINK; @@ -76,7 +76,7 @@ impl Cha { } #[inline] - pub fn from_dummy(_url: &Url, ft: Option) -> Self { + pub fn from_dummy(_url: &UrlBuf, ft: Option) -> Self { let mut me = ft.map(Self::from_half_ft).unwrap_or_default(); #[cfg(unix)] if _url.urn().is_hidden() { diff --git a/yazi-fs/src/cha/kind.rs b/yazi-fs/src/cha/kind.rs index 2a7861bd..5b6c3f28 100644 --- a/yazi-fs/src/cha/kind.rs +++ b/yazi-fs/src/cha/kind.rs @@ -1,7 +1,7 @@ use std::fs::Metadata; use bitflags::bitflags; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; bitflags! { #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] @@ -20,7 +20,7 @@ bitflags! { impl ChaKind { #[inline] - pub(super) fn hidden(_url: &Url, _meta: &Metadata) -> Self { + pub(super) fn hidden(_url: &UrlBuf, _meta: &Metadata) -> Self { let mut me = Self::empty(); #[cfg(unix)] diff --git a/yazi-fs/src/cwd.rs b/yazi-fs/src/cwd.rs index e10e642f..c5d3dd93 100644 --- a/yazi-fs/src/cwd.rs +++ b/yazi-fs/src/cwd.rs @@ -1,14 +1,14 @@ use std::{env::{current_dir, set_current_dir}, ops::Deref, path::PathBuf, sync::{Arc, atomic::{AtomicBool, Ordering}}}; use arc_swap::ArcSwap; -use yazi_shared::{RoCell, url::Url}; +use yazi_shared::{RoCell, url::UrlBuf}; pub static CWD: RoCell = RoCell::new(); -pub struct Cwd(ArcSwap); +pub struct Cwd(ArcSwap); impl Deref for Cwd { - type Target = ArcSwap; + type Target = ArcSwap; fn deref(&self) -> &Self::Target { &self.0 } } @@ -21,12 +21,12 @@ impl Default for Cwd { .or_else(|| current_dir().ok()) .expect("failed to get current working directory"); - Self(ArcSwap::new(Arc::new(Url::from(p)))) + Self(ArcSwap::new(Arc::new(UrlBuf::from(p)))) } } impl Cwd { - pub fn set(&self, url: &Url) -> bool { + pub fn set(&self, url: &UrlBuf) -> bool { if self.load().as_ref() == url { return false; } diff --git a/yazi-fs/src/file.rs b/yazi-fs/src/file.rs index 2b5407d5..652b7ffe 100644 --- a/yazi-fs/src/file.rs +++ b/yazi-fs/src/file.rs @@ -1,15 +1,15 @@ use std::{ffi::OsStr, fs::{FileType, Metadata}, hash::{BuildHasher, Hash, Hasher}, ops::Deref}; use anyhow::Result; -use yazi_shared::url::{Uri, Url, Urn, UrnBuf}; +use yazi_shared::url::{Uri, UrlBuf, Urn, UrnBuf}; use crate::{cha::Cha, provider}; #[derive(Clone, Debug, Default)] pub struct File { - pub url: Url, + pub url: UrlBuf, pub cha: Cha, - pub link_to: Option, + pub link_to: Option, } impl Deref for File { @@ -21,13 +21,13 @@ impl Deref for File { impl File { #[inline] - pub async fn new(url: Url) -> Result { + pub async fn new(url: UrlBuf) -> Result { let meta = provider::symlink_metadata(&url).await?; Ok(Self::from_follow(url, meta).await) } #[inline] - pub async fn from_follow(url: Url, meta: Metadata) -> Self { + pub async fn from_follow(url: UrlBuf, meta: Metadata) -> Self { let link_to = if meta.is_symlink() { provider::read_link(&url).await.ok() } else { None }; let cha = Cha::from_follow(&url, meta).await; @@ -36,7 +36,7 @@ impl File { } #[inline] - pub fn from_dummy(url: Url, ft: Option) -> Self { + pub fn from_dummy(url: UrlBuf, ft: Option) -> Self { let cha = Cha::from_dummy(&url, ft); Self { url, cha, link_to: None } } @@ -45,7 +45,7 @@ impl File { pub fn hash_u64(&self) -> u64 { foldhash::fast::FixedState::default().hash_one(self) } #[inline] - pub fn chdir(&self, wd: &Url) -> Self { + pub fn chdir(&self, wd: &UrlBuf) -> Self { Self { url: self.url.rebase(wd), cha: self.cha, link_to: self.link_to.clone() } } } @@ -53,7 +53,7 @@ impl File { impl File { // --- Url #[inline] - pub fn url_owned(&self) -> Url { self.url.to_owned() } + pub fn url_owned(&self) -> UrlBuf { self.url.to_owned() } #[inline] pub fn uri(&self) -> &Uri { self.url.uri() } diff --git a/yazi-fs/src/files.rs b/yazi-fs/src/files.rs index c8711370..9c05d1aa 100644 --- a/yazi-fs/src/files.rs +++ b/yazi-fs/src/files.rs @@ -1,7 +1,7 @@ use std::{collections::{HashMap, HashSet}, mem, ops::{Deref, DerefMut, Not}}; use tokio::{select, sync::mpsc::{self, UnboundedReceiver}}; -use yazi_shared::{Id, url::{Url, Urn, UrnBuf}}; +use yazi_shared::{Id, url::{UrlBuf, Urn, UrnBuf}}; use super::{FilesSorter, Filter}; use crate::{FILES_TICKET, File, FilesOp, SortBy, cha::Cha, mounts::PARTITIONS, provider::{self, DirEntry}}; @@ -34,7 +34,7 @@ impl DerefMut for Files { impl Files { pub fn new(show_hidden: bool) -> Self { Self { show_hidden, ..Default::default() } } - pub async fn from_dir(dir: &Url) -> std::io::Result> { + pub async fn from_dir(dir: &UrlBuf) -> std::io::Result> { let mut it = provider::read_dir(dir).await?; let (tx, rx) = mpsc::unbounded_channel(); @@ -55,7 +55,7 @@ impl Files { Ok(rx) } - pub async fn from_dir_bulk(dir: &Url) -> std::io::Result> { + pub async fn from_dir_bulk(dir: &UrlBuf) -> std::io::Result> { let mut it = provider::read_dir(dir).await?; let mut entries = Vec::with_capacity(5000); while let Ok(Some(entry)) = it.next_entry().await { @@ -85,7 +85,7 @@ impl Files { ) } - pub async fn assert_stale(dir: &Url, cha: Cha) -> Option { + pub async fn assert_stale(dir: &UrlBuf, cha: Cha) -> Option { use std::io::ErrorKind; match Cha::from_url(dir).await { Ok(c) if !c.is_dir() => FilesOp::issue_error(dir, ErrorKind::NotADirectory).await, diff --git a/yazi-fs/src/fns.rs b/yazi-fs/src/fns.rs index eaf24171..bd8c36e7 100644 --- a/yazi-fs/src/fns.rs +++ b/yazi-fs/src/fns.rs @@ -4,12 +4,12 @@ use std::{borrow::Cow, collections::{HashMap, HashSet}, ffi::{OsStr, OsString}, use anyhow::{Result, bail}; use tokio::{fs, io, select, sync::{mpsc, oneshot}, time}; -use yazi_shared::url::{Component, Url}; +use yazi_shared::url::{Component, UrlBuf}; use crate::{cha::Cha, provider}; #[inline] -pub async fn maybe_exists(u: impl AsRef) -> bool { +pub async fn maybe_exists(u: impl AsRef) -> bool { match provider::symlink_metadata(u).await { Ok(_) => true, Err(e) => e.kind() != io::ErrorKind::NotFound, @@ -17,7 +17,7 @@ pub async fn maybe_exists(u: impl AsRef) -> bool { } #[inline] -pub async fn must_be_dir(u: impl AsRef) -> bool { +pub async fn must_be_dir(u: impl AsRef) -> bool { provider::metadata(u).await.is_ok_and(|m| m.is_dir()) } @@ -83,7 +83,7 @@ async fn _paths_to_same_file(a: &Path, b: &Path) -> std::io::Result { Ok(final_name(a).await? == final_name(b).await?) } -pub async fn realname(u: &Url) -> Option { +pub async fn realname(u: &UrlBuf) -> Option { let name = u.file_name()?; if *u == provider::canonicalize(u).await.ok()? { return None; @@ -159,8 +159,8 @@ pub async fn realname_unchecked<'a>( } pub fn copy_with_progress( - from: &Url, - to: &Url, + from: &UrlBuf, + to: &UrlBuf, cha: Cha, ) -> mpsc::Receiver> { let (tx, rx) = mpsc::channel(1); @@ -212,7 +212,7 @@ pub fn copy_with_progress( rx } -async fn _copy_with_progress(from: Url, to: Url, cha: Cha) -> io::Result { +async fn _copy_with_progress(from: UrlBuf, to: UrlBuf, cha: Cha) -> io::Result { let mut ft = std::fs::FileTimes::new(); cha.atime.map(|t| ft = ft.set_accessed(t)); cha.mtime.map(|t| ft = ft.set_modified(t)); @@ -260,7 +260,7 @@ async fn _copy_with_progress(from: Url, to: Url, cha: Cha) -> io::Result { } } -pub async fn remove_dir_clean(dir: &Url) { +pub async fn remove_dir_clean(dir: &UrlBuf) { let Ok(mut it) = provider::read_dir(dir).await else { return }; while let Ok(Some(entry)) = it.next_entry().await { @@ -330,7 +330,7 @@ pub fn permissions(m: libc::mode_t, dummy: bool) -> String { // Find the max common root in a list of urls // e.g. /a/b/c, /a/b/d -> /a/b // /aa/bb/cc, /aa/dd/ee -> /aa -pub fn max_common_root(urls: &[Url]) -> usize { +pub fn max_common_root(urls: &[UrlBuf]) -> usize { if urls.is_empty() { return 0; } else if urls.len() == 1 { @@ -371,7 +371,7 @@ pub fn max_common_root(urls: &[Url]) -> usize { fn test_max_common_root() { fn assert(input: &[&str], expected: &str) { use std::str::FromStr; - let urls: Vec<_> = input.iter().copied().map(Url::from_str).collect::>().unwrap(); + let urls: Vec<_> = input.iter().copied().map(UrlBuf::from_str).collect::>().unwrap(); let mut comp = urls[0].components(); for _ in 0..comp.clone().count() - max_common_root(&urls) { diff --git a/yazi-fs/src/op.rs b/yazi-fs/src/op.rs index 86d837ec..008b817d 100644 --- a/yazi-fs/src/op.rs +++ b/yazi-fs/src/op.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use yazi_macro::relay; -use yazi_shared::{Id, Ids, url::{Url, UrnBuf}}; +use yazi_shared::{Id, Ids, url::{UrlBuf, UrnBuf}}; use super::File; use crate::{cha::Cha, maybe_exists}; @@ -10,21 +10,21 @@ pub static FILES_TICKET: Ids = Ids::new(); #[derive(Clone, Debug)] pub enum FilesOp { - Full(Url, Vec, Cha), - Part(Url, Vec, Id), - Done(Url, Cha, Id), - Size(Url, HashMap), - IOErr(Url, std::io::ErrorKind), + Full(UrlBuf, Vec, Cha), + Part(UrlBuf, Vec, Id), + Done(UrlBuf, Cha, Id), + Size(UrlBuf, HashMap), + IOErr(UrlBuf, std::io::ErrorKind), - Creating(Url, Vec), - Deleting(Url, HashSet), - Updating(Url, HashMap), - Upserting(Url, HashMap), + Creating(UrlBuf, Vec), + Deleting(UrlBuf, HashSet), + Updating(UrlBuf, HashMap), + Upserting(UrlBuf, HashMap), } impl FilesOp { #[inline] - pub fn cwd(&self) -> &Url { + pub fn cwd(&self) -> &UrlBuf { match self { Self::Full(u, ..) => u, Self::Part(u, ..) => u, @@ -44,13 +44,13 @@ impl FilesOp { yazi_shared::event::Event::Call(relay!(mgr:update_files).with_any("op", self).into()).emit(); } - pub fn prepare(cwd: &Url) -> Id { + pub fn prepare(cwd: &UrlBuf) -> Id { let ticket = FILES_TICKET.next(); Self::Part(cwd.clone(), vec![], ticket).emit(); ticket } - pub fn rename(map: HashMap) { + pub fn rename(map: HashMap) { let mut parents: HashMap<_, (HashSet<_>, HashMap<_, _>)> = Default::default(); for (o, n) in map { let Some(o_p) = o.parent_url() else { continue }; @@ -95,7 +95,7 @@ impl FilesOp { } } - pub fn chdir(&self, wd: &Url) -> Self { + pub fn chdir(&self, wd: &UrlBuf) -> Self { macro_rules! files { ($files:expr) => {{ $files.iter().map(|file| file.chdir(wd)).collect() }}; } @@ -118,7 +118,7 @@ impl FilesOp { } } - pub async fn issue_error(cwd: &Url, kind: std::io::ErrorKind) { + pub async fn issue_error(cwd: &UrlBuf, kind: std::io::ErrorKind) { use std::io::ErrorKind; if kind != ErrorKind::NotFound { Self::IOErr(cwd.clone(), kind).emit(); @@ -129,7 +129,7 @@ impl FilesOp { } } - pub fn diff_recoverable(&self, contains: impl Fn(&Url) -> bool) -> (Vec, Vec) { + pub fn diff_recoverable(&self, contains: impl Fn(&UrlBuf) -> bool) -> (Vec, Vec) { match self { Self::Deleting(cwd, urns) => (urns.iter().map(|u| cwd.join(u)).collect(), vec![]), Self::Updating(cwd, urns) | Self::Upserting(cwd, urns) => urns diff --git a/yazi-fs/src/path/clean.rs b/yazi-fs/src/path/clean.rs index cdeed84f..5c380c09 100644 --- a/yazi-fs/src/path/clean.rs +++ b/yazi-fs/src/path/clean.rs @@ -1,15 +1,15 @@ use std::{borrow::Cow, path::{Path, PathBuf}}; -use yazi_shared::url::{Loc, Url}; +use yazi_shared::{loc::LocBuf, url::UrlBuf}; -pub fn clean_url<'a>(url: impl Into>) -> Url { +pub fn clean_url<'a>(url: impl Into>) -> UrlBuf { let cow = url.into(); let (path, uri, urn) = clean_path_impl(&cow.loc, cow.loc.base().count(), cow.loc.trail().count()); - let loc = Loc::with(path, uri, urn).expect("Failed to create Loc from cleaned path"); + let loc = LocBuf::with(path, uri, urn).expect("Failed to create Loc from cleaned path"); match cow { - Cow::Borrowed(u) => Url { loc, scheme: u.scheme.clone() }, - Cow::Owned(u) => Url { loc, scheme: u.scheme }, + Cow::Borrowed(u) => UrlBuf { loc, scheme: u.scheme.clone() }, + Cow::Owned(u) => UrlBuf { loc, scheme: u.scheme }, } } @@ -70,7 +70,7 @@ mod tests { ]; for (input, expected) in cases { - let input: Url = input.parse()?; + let input: UrlBuf = input.parse()?; #[cfg(unix)] assert_eq!(format!("{:?}", clean_url(input)), expected); #[cfg(windows)] diff --git a/yazi-fs/src/path/expand.rs b/yazi-fs/src/path/expand.rs index 8e0421ef..536fa2ba 100644 --- a/yazi-fs/src/path/expand.rs +++ b/yazi-fs/src/path/expand.rs @@ -1,13 +1,15 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}, path::{Path, PathBuf}}; -use yazi_shared::url::{Loc, Url}; +use yazi_shared::{loc::LocBuf, url::UrlBuf}; use crate::{CWD, path::clean_url}; #[inline] -pub fn expand_url<'a>(url: impl AsRef) -> Url { clean_url(expand_url_impl(url.as_ref())) } +pub fn expand_url<'a>(url: impl AsRef) -> UrlBuf { + clean_url(expand_url_impl(url.as_ref())) +} -fn expand_url_impl(url: &Url) -> Cow<'_, Url> { +fn expand_url_impl(url: &UrlBuf) -> Cow<'_, UrlBuf> { let (o_base, o_rest, o_urn) = url.loc.triple(); let n_base = expand_variables(o_base); @@ -20,14 +22,14 @@ fn expand_url_impl(url: &Url) -> Cow<'_, Url> { let uri_count = url.uri().count() as isize; let urn_count = url.urn().count() as isize; - let loc = Loc::with( + let loc = LocBuf::with( PathBuf::from_iter([n_base, n_rest, n_urn]), (uri_count + rest_diff + urn_diff) as usize, (urn_count + urn_diff) as usize, ) .expect("Failed to create Loc from expanded path"); - let url = Url { loc, scheme: url.scheme.clone() }; + let url = UrlBuf { loc, scheme: url.scheme.clone() }; match absolute_url(&url) { Cow::Borrowed(_) => url.into(), Cow::Owned(u) => u.into(), @@ -60,36 +62,36 @@ fn expand_variables(p: &Path) -> Cow<'_, Path> { } } -fn absolute_url(url: &Url) -> Cow<'_, Url> { +fn absolute_url(url: &UrlBuf) -> Cow<'_, UrlBuf> { let b = url.loc.as_os_str().as_encoded_bytes(); let local = !url.scheme.is_virtual(); if cfg!(windows) && local && b.len() == 2 && b[1] == b':' && b[0].is_ascii_alphabetic() { - let loc = Loc::with( + let loc = LocBuf::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 }, ) .expect("Failed to create Loc from drive letter"); - Url { loc, scheme: url.scheme.clone() }.into() + UrlBuf { loc, scheme: url.scheme.clone() }.into() } else if local && let Ok(rest) = url.loc.strip_prefix("~/") && let Some(home) = dirs::home_dir() && home.is_absolute() { let add = home.components().count() - 1; // Home root ("~") has offset by the absolute root ("/") - let loc = Loc::with( + let loc = LocBuf::with( home.join(rest), url.uri().count() + if url.has_base() { 0 } else { add }, url.urn().count() + if url.has_trail() { 0 } else { add }, ) .expect("Failed to create Loc from home directory"); - Url { loc, scheme: url.scheme.clone() }.into() + UrlBuf { loc, scheme: url.scheme.clone() }.into() } else if !url.is_absolute() { let cwd = CWD.load(); - let loc = Loc::with(cwd.loc.join(&url.loc), url.uri().count(), url.urn().count()) + let loc = LocBuf::with(cwd.loc.join(&url.loc), url.uri().count(), url.urn().count()) .expect("Failed to create Loc from relative path"); - Url { loc, scheme: cwd.scheme.clone() }.into() + UrlBuf { loc, scheme: cwd.scheme.clone() }.into() } else { url.into() } @@ -149,7 +151,7 @@ mod tests { ]; for (input, expected) in cases { - let u: Url = input.parse()?; + let u: UrlBuf = input.parse()?; assert_eq!(format!("{:?}", expand_url(u)), expected); } diff --git a/yazi-fs/src/path/path.rs b/yazi-fs/src/path/path.rs index 4e1b4a3e..1c91f4f5 100644 --- a/yazi-fs/src/path/path.rs +++ b/yazi-fs/src/path/path.rs @@ -1,11 +1,11 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}, future::Future, io, path::PathBuf}; use anyhow::{Result, bail}; -use yazi_shared::url::{Loc, Url}; +use yazi_shared::{loc::LocBuf, url::UrlBuf}; use crate::provider; -pub fn skip_url(url: &Url, n: usize) -> Cow<'_, OsStr> { +pub fn skip_url(url: &UrlBuf, n: usize) -> Cow<'_, OsStr> { let mut it = url.components(); for _ in 0..n { if it.next().is_none() { @@ -15,7 +15,7 @@ pub fn skip_url(url: &Url, n: usize) -> Cow<'_, OsStr> { it.os_str() } -pub async fn unique_name(u: Url, append: F) -> io::Result +pub async fn unique_name(u: UrlBuf, append: F) -> io::Result where F: Future, { @@ -26,7 +26,7 @@ where } } -async fn _unique_name(mut url: Url, append: bool) -> io::Result { +async fn _unique_name(mut url: UrlBuf, append: bool) -> io::Result { let Some(stem) = url.file_stem().map(|s| s.to_owned()) else { return Err(io::Error::new(io::ErrorKind::InvalidInput, "empty file stem")); }; @@ -63,7 +63,7 @@ async fn _unique_name(mut url: Url, append: bool) -> io::Result { Ok(url) } -pub fn url_relative_to<'a>(from: &Url, to: &'a Url) -> Result> { +pub fn url_relative_to<'a>(from: &UrlBuf, to: &'a UrlBuf) -> Result> { use yazi_shared::url::Component::*; if from.is_absolute() != to.is_absolute() { @@ -75,7 +75,7 @@ pub fn url_relative_to<'a>(from: &Url, to: &'a Url) -> Result> { } if from.covariant(to) { - return Ok(Url { loc: Loc::zeroed("."), scheme: to.scheme.clone() }.into()); + return Ok(UrlBuf { loc: LocBuf::zeroed("."), scheme: to.scheme.clone() }.into()); } let (mut f_it, mut t_it) = (from.components(), to.components()); @@ -97,7 +97,7 @@ pub fn url_relative_to<'a>(from: &Url, to: &'a Url) -> Result> { let rest = t_head.into_iter().chain(t_it); let buf: PathBuf = dots.chain(rest).collect(); - Ok(Url { loc: Loc::zeroed(buf), scheme: to.scheme.clone() }.into()) + Ok(UrlBuf { loc: LocBuf::zeroed(buf), scheme: to.scheme.clone() }.into()) } #[cfg(windows)] diff --git a/yazi-fs/src/provider/dir_entry.rs b/yazi-fs/src/provider/dir_entry.rs index 4aa54c52..53a89f3e 100644 --- a/yazi-fs/src/provider/dir_entry.rs +++ b/yazi-fs/src/provider/dir_entry.rs @@ -1,6 +1,6 @@ use std::{ffi::OsString, io}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub enum DirEntry { Local(super::local::DirEntry), @@ -8,7 +8,7 @@ pub enum DirEntry { impl DirEntry { #[must_use] - pub fn url(&self) -> Url { + pub fn url(&self) -> UrlBuf { match self { DirEntry::Local(local) => local.url(), } @@ -41,7 +41,7 @@ pub enum DirEntrySync { impl DirEntrySync { #[must_use] - pub fn url(&self) -> Url { + pub fn url(&self) -> UrlBuf { match self { DirEntrySync::Local(local) => local.url(), } diff --git a/yazi-fs/src/provider/local/dir_entry.rs b/yazi-fs/src/provider/local/dir_entry.rs index ea938397..ea7daa81 100644 --- a/yazi-fs/src/provider/local/dir_entry.rs +++ b/yazi-fs/src/provider/local/dir_entry.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct DirEntry(tokio::fs::DirEntry); @@ -20,7 +20,7 @@ impl From for crate::provider::DirEntry { impl DirEntry { #[must_use] - pub fn url(&self) -> Url { self.0.path().into() } + pub fn url(&self) -> UrlBuf { self.0.path().into() } } // --- DirEntrySync @@ -42,5 +42,5 @@ impl From for crate::provider::DirEntrySync { impl DirEntrySync { #[must_use] - pub fn url(&self) -> Url { self.0.path().into() } + pub fn url(&self) -> UrlBuf { self.0.path().into() } } diff --git a/yazi-fs/src/provider/provider.rs b/yazi-fs/src/provider/provider.rs index 9f5c6ffc..6ef31783 100644 --- a/yazi-fs/src/provider/provider.rs +++ b/yazi-fs/src/provider/provider.rs @@ -1,11 +1,11 @@ use std::io; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; use crate::provider::{ReadDir, ReadDirSync, RwFile, local::Local}; #[inline] -pub async fn canonicalize(url: impl AsRef) -> io::Result { +pub async fn canonicalize(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::canonicalize(path).await.map(Into::into) } else { @@ -14,7 +14,7 @@ pub async fn canonicalize(url: impl AsRef) -> io::Result { } #[inline] -pub async fn create(url: impl AsRef) -> io::Result { +pub async fn create(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::create(path).await.map(Into::into) } else { @@ -23,7 +23,7 @@ pub async fn create(url: impl AsRef) -> io::Result { } #[inline] -pub async fn create_dir(url: impl AsRef) -> io::Result<()> { +pub async fn create_dir(url: impl AsRef) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::create_dir(path).await } else { @@ -32,7 +32,7 @@ pub async fn create_dir(url: impl AsRef) -> io::Result<()> { } #[inline] -pub async fn create_dir_all(url: impl AsRef) -> io::Result<()> { +pub async fn create_dir_all(url: impl AsRef) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::create_dir_all(path).await } else { @@ -41,7 +41,7 @@ pub async fn create_dir_all(url: impl AsRef) -> io::Result<()> { } #[inline] -pub async fn hard_link(original: impl AsRef, link: impl AsRef) -> io::Result<()> { +pub async fn hard_link(original: impl AsRef, link: impl AsRef) -> io::Result<()> { if let (Some(original), Some(link)) = (original.as_ref().as_path(), link.as_ref().as_path()) { Local::hard_link(original, link).await } else { @@ -50,7 +50,7 @@ pub async fn hard_link(original: impl AsRef, link: impl AsRef) -> io:: } #[inline] -pub async fn metadata(url: impl AsRef) -> io::Result { +pub async fn metadata(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::metadata(path).await } else { @@ -59,7 +59,7 @@ pub async fn metadata(url: impl AsRef) -> io::Result { } #[inline] -pub async fn open(url: impl AsRef) -> io::Result { +pub async fn open(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::open(path).await.map(Into::into) } else { @@ -68,7 +68,7 @@ pub async fn open(url: impl AsRef) -> io::Result { } #[inline] -pub async fn read_dir(url: impl AsRef) -> io::Result { +pub async fn read_dir(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::read_dir(path).await.map(Into::into) } else { @@ -77,7 +77,7 @@ pub async fn read_dir(url: impl AsRef) -> io::Result { } #[inline] -pub fn read_dir_sync(url: impl AsRef) -> io::Result { +pub fn read_dir_sync(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::read_dir_sync(path).map(Into::into) } else { @@ -86,7 +86,7 @@ pub fn read_dir_sync(url: impl AsRef) -> io::Result { } #[inline] -pub async fn read_link(url: impl AsRef) -> io::Result { +pub async fn read_link(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::read_link(path).await.map(Into::into) } else { @@ -95,7 +95,7 @@ pub async fn read_link(url: impl AsRef) -> io::Result { } #[inline] -pub async fn remove_dir(url: impl AsRef) -> io::Result<()> { +pub async fn remove_dir(url: impl AsRef) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::remove_dir(path).await } else { @@ -104,7 +104,7 @@ pub async fn remove_dir(url: impl AsRef) -> io::Result<()> { } #[inline] -pub async fn remove_dir_all(url: impl AsRef) -> io::Result<()> { +pub async fn remove_dir_all(url: impl AsRef) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::remove_dir_all(path).await } else { @@ -113,7 +113,7 @@ pub async fn remove_dir_all(url: impl AsRef) -> io::Result<()> { } #[inline] -pub async fn remove_file(url: impl AsRef) -> io::Result<()> { +pub async fn remove_file(url: impl AsRef) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::remove_file(path).await } else { @@ -122,7 +122,7 @@ pub async fn remove_file(url: impl AsRef) -> io::Result<()> { } #[inline] -pub async fn rename(from: impl AsRef, to: impl AsRef) -> io::Result<()> { +pub async fn rename(from: impl AsRef, to: impl AsRef) -> io::Result<()> { if let (Some(from), Some(to)) = (from.as_ref().as_path(), to.as_ref().as_path()) { Local::rename(from, to).await } else { @@ -131,7 +131,7 @@ pub async fn rename(from: impl AsRef, to: impl AsRef) -> io::Result<() } #[inline] -pub async fn symlink_dir(original: impl AsRef, link: impl AsRef) -> io::Result<()> { +pub async fn symlink_dir(original: impl AsRef, link: impl AsRef) -> io::Result<()> { if let (Some(original), Some(link)) = (original.as_ref().as_path(), link.as_ref().as_path()) { Local::symlink_dir(original, link).await } else { @@ -140,7 +140,10 @@ pub async fn symlink_dir(original: impl AsRef, link: impl AsRef) -> io } #[inline] -pub async fn symlink_file(original: impl AsRef, link: impl AsRef) -> io::Result<()> { +pub async fn symlink_file( + original: impl AsRef, + link: impl AsRef, +) -> io::Result<()> { if let (Some(original), Some(link)) = (original.as_ref().as_path(), link.as_ref().as_path()) { Local::symlink_file(original, link).await } else { @@ -149,7 +152,7 @@ pub async fn symlink_file(original: impl AsRef, link: impl AsRef) -> i } #[inline] -pub async fn symlink_metadata(url: impl AsRef) -> io::Result { +pub async fn symlink_metadata(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::symlink_metadata(path).await } else { @@ -157,7 +160,7 @@ pub async fn symlink_metadata(url: impl AsRef) -> io::Result) -> io::Result { +pub fn symlink_metadata_sync(url: impl AsRef) -> io::Result { if let Some(path) = url.as_ref().as_path() { Local::symlink_metadata_sync(path) } else { @@ -166,7 +169,7 @@ pub fn symlink_metadata_sync(url: impl AsRef) -> io::Result, contents: impl AsRef<[u8]>) -> io::Result<()> { +pub async fn write(url: impl AsRef, contents: impl AsRef<[u8]>) -> io::Result<()> { if let Some(path) = url.as_ref().as_path() { Local::write(path, contents).await } else { diff --git a/yazi-parser/src/cmp/show.rs b/yazi-parser/src/cmp/show.rs index 5dc3d304..5af4e9e9 100644 --- a/yazi-parser/src/cmp/show.rs +++ b/yazi-parser/src/cmp/show.rs @@ -2,12 +2,12 @@ use std::{ffi::OsString, path::MAIN_SEPARATOR_STR}; use anyhow::bail; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{Id, event::CmdCow, url::{Url, UrnBuf}}; +use yazi_shared::{Id, event::CmdCow, url::{UrlBuf, UrnBuf}}; #[derive(Debug, Default)] pub struct ShowOpt { pub cache: Vec, - pub cache_name: Url, + pub cache_name: UrlBuf, pub word: UrnBuf, pub ticket: Id, } diff --git a/yazi-parser/src/mgr/cd.rs b/yazi-parser/src/mgr/cd.rs index d73d85bf..1a7fc949 100644 --- a/yazi-parser/src/mgr/cd.rs +++ b/yazi-parser/src/mgr/cd.rs @@ -1,10 +1,10 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_fs::path::expand_url; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct CdOpt { - pub target: Url, + pub target: UrlBuf, pub interactive: bool, pub source: CdSource, } @@ -21,8 +21,10 @@ impl From for CdOpt { } } -impl From<(Url, CdSource)> for CdOpt { - fn from((target, source): (Url, CdSource)) -> Self { Self { target, interactive: false, source } } +impl From<(UrlBuf, CdSource)> for CdOpt { + fn from((target, source): (UrlBuf, CdSource)) -> Self { + Self { target, interactive: false, source } + } } impl FromLua for CdOpt { diff --git a/yazi-parser/src/mgr/open_do.rs b/yazi-parser/src/mgr/open_do.rs index 930dd0d1..eaf55cbc 100644 --- a/yazi-parser/src/mgr/open_do.rs +++ b/yazi-parser/src/mgr/open_do.rs @@ -1,11 +1,11 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug, Default)] pub struct OpenDoOpt { - pub cwd: Url, - pub hovered: Url, - pub targets: Vec<(Url, &'static str)>, + pub cwd: UrlBuf, + pub hovered: UrlBuf, + pub targets: Vec<(UrlBuf, &'static str)>, pub interactive: bool, } diff --git a/yazi-parser/src/mgr/open_with.rs b/yazi-parser/src/mgr/open_with.rs index 7b86a010..300ef569 100644 --- a/yazi-parser/src/mgr/open_with.rs +++ b/yazi-parser/src/mgr/open_with.rs @@ -3,13 +3,13 @@ use std::borrow::Cow; use anyhow::anyhow; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_config::opener::OpenerRule; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct OpenWithOpt { pub opener: Cow<'static, OpenerRule>, - pub cwd: Url, - pub targets: Vec, + pub cwd: UrlBuf, + pub targets: Vec, } impl TryFrom for OpenWithOpt { diff --git a/yazi-parser/src/mgr/peek.rs b/yazi-parser/src/mgr/peek.rs index 319b92c2..22b54672 100644 --- a/yazi-parser/src/mgr/peek.rs +++ b/yazi-parser/src/mgr/peek.rs @@ -1,11 +1,11 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::{CmdCow, Data}, url::Url}; +use yazi_shared::{event::{CmdCow, Data}, url::UrlBuf}; #[derive(Debug, Default)] pub struct PeekOpt { pub skip: Option, pub force: bool, - pub only_if: Option, + pub only_if: Option, pub upper_bound: bool, } diff --git a/yazi-parser/src/mgr/remove.rs b/yazi-parser/src/mgr/remove.rs index 2d3e0850..6dc4ec3e 100644 --- a/yazi-parser/src/mgr/remove.rs +++ b/yazi-parser/src/mgr/remove.rs @@ -1,12 +1,12 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct RemoveOpt { pub force: bool, pub permanently: bool, pub hovered: bool, - pub targets: Vec, + pub targets: Vec, } impl From for RemoveOpt { diff --git a/yazi-parser/src/mgr/reveal.rs b/yazi-parser/src/mgr/reveal.rs index 4bb15fa6..76db1c81 100644 --- a/yazi-parser/src/mgr/reveal.rs +++ b/yazi-parser/src/mgr/reveal.rs @@ -1,12 +1,12 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_fs::path::expand_url; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; use crate::mgr::CdSource; #[derive(Debug)] pub struct RevealOpt { - pub target: Url, + pub target: UrlBuf, pub source: CdSource, pub no_dummy: bool, } @@ -23,12 +23,12 @@ impl From for RevealOpt { } } -impl From for RevealOpt { - fn from(target: Url) -> Self { Self { target, source: CdSource::Reveal, no_dummy: false } } +impl From for RevealOpt { + fn from(target: UrlBuf) -> Self { Self { target, source: CdSource::Reveal, no_dummy: false } } } -impl From<(Url, CdSource)> for RevealOpt { - fn from((target, source): (Url, CdSource)) -> Self { Self { target, source, no_dummy: false } } +impl From<(UrlBuf, CdSource)> for RevealOpt { + fn from((target, source): (UrlBuf, CdSource)) -> Self { Self { target, source, no_dummy: false } } } impl FromLua for RevealOpt { diff --git a/yazi-parser/src/mgr/shell.rs b/yazi-parser/src/mgr/shell.rs index 28e5d138..b705904c 100644 --- a/yazi-parser/src/mgr/shell.rs +++ b/yazi-parser/src/mgr/shell.rs @@ -1,11 +1,11 @@ use anyhow::bail; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{SStr, event::{CmdCow, Data}, url::Url}; +use yazi_shared::{SStr, event::{CmdCow, Data}, url::UrlBuf}; #[derive(Debug)] pub struct ShellOpt { pub run: SStr, - pub cwd: Option, + pub cwd: Option, pub block: bool, pub orphan: bool, diff --git a/yazi-parser/src/mgr/tab_create.rs b/yazi-parser/src/mgr/tab_create.rs index 3d23a6a3..f974ed67 100644 --- a/yazi-parser/src/mgr/tab_create.rs +++ b/yazi-parser/src/mgr/tab_create.rs @@ -1,11 +1,11 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use yazi_boot::BOOT; use yazi_fs::path::expand_url; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct TabCreateOpt { - pub wd: Option, + pub wd: Option, } impl From for TabCreateOpt { diff --git a/yazi-parser/src/mgr/toggle.rs b/yazi-parser/src/mgr/toggle.rs index 39244157..f86d185e 100644 --- a/yazi-parser/src/mgr/toggle.rs +++ b/yazi-parser/src/mgr/toggle.rs @@ -1,9 +1,9 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct ToggleOpt { - pub url: Option, + pub url: Option, pub state: Option, } diff --git a/yazi-parser/src/mgr/toggle_all.rs b/yazi-parser/src/mgr/toggle_all.rs index 00568a29..d49fda82 100644 --- a/yazi-parser/src/mgr/toggle_all.rs +++ b/yazi-parser/src/mgr/toggle_all.rs @@ -1,9 +1,9 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct ToggleAllOpt { - pub urls: Vec, + pub urls: Vec, pub state: Option, } diff --git a/yazi-parser/src/mgr/update_paged.rs b/yazi-parser/src/mgr/update_paged.rs index 3e7cc99e..720f8600 100644 --- a/yazi-parser/src/mgr/update_paged.rs +++ b/yazi-parser/src/mgr/update_paged.rs @@ -1,10 +1,10 @@ use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::{CmdCow, Data}, url::Url}; +use yazi_shared::{event::{CmdCow, Data}, url::UrlBuf}; #[derive(Debug, Default)] pub struct UpdatePagedOpt { pub page: Option, - pub only_if: Option, + pub only_if: Option, } impl From for UpdatePagedOpt { diff --git a/yazi-parser/src/mgr/update_peeked.rs b/yazi-parser/src/mgr/update_peeked.rs index 381276aa..57f494f3 100644 --- a/yazi-parser/src/mgr/update_peeked.rs +++ b/yazi-parser/src/mgr/update_peeked.rs @@ -35,7 +35,7 @@ impl IntoLua for UpdatePeekedOpt { // --- Lock #[derive(Debug, Default)] pub struct PreviewLock { - pub url: yazi_shared::url::Url, + pub url: yazi_shared::url::UrlBuf, pub cha: yazi_fs::cha::Cha, pub mime: String, diff --git a/yazi-parser/src/mgr/update_spotted.rs b/yazi-parser/src/mgr/update_spotted.rs index 3f4ebcd3..b7dfe38d 100644 --- a/yazi-parser/src/mgr/update_spotted.rs +++ b/yazi-parser/src/mgr/update_spotted.rs @@ -35,7 +35,7 @@ impl IntoLua for UpdateSpottedOpt { // --- Lock #[derive(Debug)] pub struct SpotLock { - pub url: yazi_shared::url::Url, + pub url: yazi_shared::url::UrlBuf, pub cha: yazi_fs::cha::Cha, pub mime: String, diff --git a/yazi-parser/src/mgr/update_tasks.rs b/yazi-parser/src/mgr/update_tasks.rs index aeb6c7a3..c2397d15 100644 --- a/yazi-parser/src/mgr/update_tasks.rs +++ b/yazi-parser/src/mgr/update_tasks.rs @@ -1,10 +1,10 @@ use anyhow::bail; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; #[derive(Debug)] pub struct UpdateTasksOpt { - pub urls: Vec, + pub urls: Vec, } impl TryFrom for UpdateTasksOpt { diff --git a/yazi-parser/src/mgr/update_yanked.rs b/yazi-parser/src/mgr/update_yanked.rs index db12e28d..c1771443 100644 --- a/yazi-parser/src/mgr/update_yanked.rs +++ b/yazi-parser/src/mgr/update_yanked.rs @@ -4,17 +4,17 @@ use anyhow::bail; use mlua::{AnyUserData, ExternalError, FromLua, IntoLua, Lua, MetaMethod, MultiValue, ObjectLike, UserData, UserDataFields, UserDataMethods, Value}; use serde::{Deserialize, Serialize}; use yazi_binding::get_metatable; -use yazi_shared::{event::CmdCow, url::CovUrl}; +use yazi_shared::{event::CmdCow, url::UrlCov}; type Iter = yazi_binding::Iter< - std::iter::Map, fn(CovUrl) -> yazi_binding::Url>, + std::iter::Map, fn(UrlCov) -> yazi_binding::Url>, yazi_binding::Url, >; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct UpdateYankedOpt<'a> { pub cut: bool, - pub urls: Cow<'a, HashSet>, + pub urls: Cow<'a, HashSet>, } impl TryFrom for UpdateYankedOpt<'_> { diff --git a/yazi-parser/src/tasks/process_exec.rs b/yazi-parser/src/tasks/process_exec.rs index 2b712f3e..45157f55 100644 --- a/yazi-parser/src/tasks/process_exec.rs +++ b/yazi-parser/src/tasks/process_exec.rs @@ -4,12 +4,12 @@ use anyhow::anyhow; use mlua::{ExternalError, FromLua, IntoLua, Lua, Value}; use tokio::sync::oneshot; use yazi_config::opener::OpenerRule; -use yazi_shared::{event::CmdCow, url::Url}; +use yazi_shared::{event::CmdCow, url::UrlBuf}; // --- Exec #[derive(Debug)] pub struct ProcessExecOpt { - pub cwd: Url, + pub cwd: UrlBuf, pub opener: Cow<'static, OpenerRule>, pub args: Vec, pub done: Option>, diff --git a/yazi-plugin/src/external/fd.rs b/yazi-plugin/src/external/fd.rs index bd1a70db..2ac725f2 100644 --- a/yazi-plugin/src/external/fd.rs +++ b/yazi-plugin/src/external/fd.rs @@ -3,10 +3,10 @@ use std::process::Stdio; use anyhow::Result; use tokio::{io::{AsyncBufReadExt, BufReader}, process::{Child, Command}, sync::mpsc::{self, UnboundedReceiver}}; use yazi_fs::File; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct FdOpt { - pub cwd: Url, + pub cwd: UrlBuf, pub hidden: bool, pub subject: String, pub args: Vec, diff --git a/yazi-plugin/src/external/rg.rs b/yazi-plugin/src/external/rg.rs index 3944677a..8fde2a2e 100644 --- a/yazi-plugin/src/external/rg.rs +++ b/yazi-plugin/src/external/rg.rs @@ -3,10 +3,10 @@ use std::process::Stdio; use anyhow::{Result, bail}; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; use yazi_fs::File; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct RgOpt { - pub cwd: Url, + pub cwd: UrlBuf, pub hidden: bool, pub subject: String, pub args: Vec, diff --git a/yazi-plugin/src/external/rga.rs b/yazi-plugin/src/external/rga.rs index ce4e9656..ae450b89 100644 --- a/yazi-plugin/src/external/rga.rs +++ b/yazi-plugin/src/external/rga.rs @@ -3,10 +3,10 @@ use std::process::Stdio; use anyhow::{Result, bail}; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::{self, UnboundedReceiver}}; use yazi_fs::File; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct RgaOpt { - pub cwd: Url, + pub cwd: UrlBuf, pub hidden: bool, pub subject: String, pub args: Vec, diff --git a/yazi-proxy/src/mgr.rs b/yazi-proxy/src/mgr.rs index b4ab30b0..f33e42b3 100644 --- a/yazi-proxy/src/mgr.rs +++ b/yazi-proxy/src/mgr.rs @@ -2,16 +2,16 @@ use std::borrow::Cow; use yazi_macro::{emit, relay}; use yazi_parser::mgr::{FilterOpt, FindDoOpt, OpenDoOpt, SearchOpt, UpdatePeekedOpt, UpdateSpottedOpt}; -use yazi_shared::{SStr, url::Url}; +use yazi_shared::{SStr, url::UrlBuf}; pub struct MgrProxy; impl MgrProxy { - pub fn cd(target: &Url) { + pub fn cd(target: &UrlBuf) { emit!(Call(relay!(mgr:cd, [target]).with("raw", true))); } - pub fn reveal(target: &Url) { + pub fn reveal(target: &UrlBuf) { emit!(Call(relay!(mgr:reveal, [target]).with("raw", true).with("no-dummy", true))); } @@ -23,7 +23,7 @@ impl MgrProxy { emit!(Call(relay!(mgr:open_do).with_any("option", opt))); } - pub fn remove_do(targets: Vec, permanently: bool) { + pub fn remove_do(targets: Vec, permanently: bool) { emit!(Call( relay!(mgr:remove_do).with("permanently", permanently).with_any("targets", targets) )); @@ -54,11 +54,11 @@ impl MgrProxy { emit!(Call(relay!(mgr:update_spotted).with_any("opt", opt))); } - pub fn update_tasks(url: &Url) { + pub fn update_tasks(url: &UrlBuf) { emit!(Call(relay!(mgr:update_tasks).with_any("urls", vec![url.clone()]))); } - pub fn update_paged_by(page: usize, only_if: &Url) { + pub fn update_paged_by(page: usize, only_if: &UrlBuf) { emit!(Call(relay!(mgr:update_paged, [page]).with_any("only-if", only_if.clone()))); } } diff --git a/yazi-proxy/src/tasks.rs b/yazi-proxy/src/tasks.rs index 5ed5bf0e..54ee8fba 100644 --- a/yazi-proxy/src/tasks.rs +++ b/yazi-proxy/src/tasks.rs @@ -4,16 +4,16 @@ use tokio::sync::oneshot; use yazi_config::opener::OpenerRule; use yazi_macro::{emit, relay}; use yazi_parser::{mgr::OpenWithOpt, tasks::ProcessExecOpt}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct TasksProxy; impl TasksProxy { - pub fn open_with(opener: Cow<'static, OpenerRule>, cwd: Url, targets: Vec) { + pub fn open_with(opener: Cow<'static, OpenerRule>, cwd: UrlBuf, targets: Vec) { emit!(Call(relay!(tasks:open_with).with_any("option", OpenWithOpt { opener, cwd, targets }))); } - pub async fn process_exec(opener: Cow<'static, OpenerRule>, cwd: Url, args: Vec) { + pub async fn process_exec(opener: Cow<'static, OpenerRule>, cwd: UrlBuf, args: Vec) { let (tx, rx) = oneshot::channel(); emit!(Call(relay!(tasks:process_exec).with_any("option", ProcessExecOpt { cwd, diff --git a/yazi-scheduler/src/file/file.rs b/yazi-scheduler/src/file/file.rs index c2868335..321bcdcf 100644 --- a/yazi-scheduler/src/file/file.rs +++ b/yazi-scheduler/src/file/file.rs @@ -5,7 +5,7 @@ use tokio::{io::{self, ErrorKind::{AlreadyExists, NotFound}}, sync::mpsc}; use tracing::warn; use yazi_config::YAZI; use yazi_fs::{SizeCalculator, cha::Cha, copy_with_progress, maybe_exists, ok_or_not_found, path::{skip_url, url_relative_to}, provider::{self, DirEntry}}; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::{FileIn, FileInDelete, FileInHardlink, FileInLink, FileInPaste, FileInTrash}; use crate::{LOW, NORMAL, TaskOp, TaskProg}; @@ -320,13 +320,13 @@ impl File { } #[inline] - async fn cha(url: &Url, follow: bool) -> io::Result { + async fn cha(url: &UrlBuf, follow: bool) -> io::Result { let meta = provider::symlink_metadata(url).await?; Ok(if follow { Cha::from_follow(url, meta).await } else { Cha::new(url, meta) }) } #[inline] - async fn cha_from(entry: DirEntry, url: &Url, follow: bool) -> io::Result { + async fn cha_from(entry: DirEntry, url: &UrlBuf, follow: bool) -> io::Result { Ok(if follow { Cha::from_follow(url, entry.metadata().await?).await } else { diff --git a/yazi-scheduler/src/file/in.rs b/yazi-scheduler/src/file/in.rs index 130fa4b5..fb2d6767 100644 --- a/yazi-scheduler/src/file/in.rs +++ b/yazi-scheduler/src/file/in.rs @@ -1,5 +1,5 @@ use yazi_fs::cha::Cha; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; #[derive(Debug)] pub enum FileIn { @@ -26,8 +26,8 @@ impl FileIn { #[derive(Clone, Debug)] pub struct FileInPaste { pub id: Id, - pub from: Url, - pub to: Url, + pub from: UrlBuf, + pub to: UrlBuf, pub cha: Option, pub cut: bool, pub follow: bool, @@ -35,7 +35,7 @@ pub struct FileInPaste { } impl FileInPaste { - pub(super) fn spawn(&self, from: Url, to: Url, cha: Cha) -> Self { + pub(super) fn spawn(&self, from: UrlBuf, to: UrlBuf, cha: Cha) -> Self { Self { id: self.id, from, @@ -52,8 +52,8 @@ impl FileInPaste { #[derive(Clone, Debug)] pub struct FileInLink { pub id: Id, - pub from: Url, - pub to: Url, + pub from: UrlBuf, + pub to: UrlBuf, pub cha: Option, pub resolve: bool, pub relative: bool, @@ -78,14 +78,14 @@ impl From for FileInLink { #[derive(Clone, Debug)] pub struct FileInHardlink { pub id: Id, - pub from: Url, - pub to: Url, + pub from: UrlBuf, + pub to: UrlBuf, pub cha: Option, pub follow: bool, } impl FileInHardlink { - pub(super) fn spawn(&self, from: Url, to: Url, cha: Cha) -> Self { + pub(super) fn spawn(&self, from: UrlBuf, to: UrlBuf, cha: Cha) -> Self { Self { id: self.id, from, to, cha: Some(cha), follow: self.follow } } } @@ -94,7 +94,7 @@ impl FileInHardlink { #[derive(Clone, Debug)] pub struct FileInDelete { pub id: Id, - pub target: Url, + pub target: UrlBuf, pub length: u64, } @@ -102,6 +102,6 @@ pub struct FileInDelete { #[derive(Clone, Debug)] pub struct FileInTrash { pub id: Id, - pub target: Url, + pub target: UrlBuf, pub length: u64, } diff --git a/yazi-scheduler/src/prework/in.rs b/yazi-scheduler/src/prework/in.rs index 5760be76..7aef8dcb 100644 --- a/yazi-scheduler/src/prework/in.rs +++ b/yazi-scheduler/src/prework/in.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use yazi_config::plugin::{Fetcher, Preloader}; -use yazi_shared::{Id, Throttle, url::Url}; +use yazi_shared::{Id, Throttle, url::UrlBuf}; #[derive(Debug)] pub enum PreworkIn { @@ -37,6 +37,6 @@ pub struct PreworkInLoad { #[derive(Debug)] pub struct PreworkInSize { pub id: Id, - pub target: Url, - pub throttle: Arc>, + pub target: UrlBuf, + pub throttle: Arc>, } diff --git a/yazi-scheduler/src/prework/prework.rs b/yazi-scheduler/src/prework/prework.rs index 915bf972..53114c85 100644 --- a/yazi-scheduler/src/prework/prework.rs +++ b/yazi-scheduler/src/prework/prework.rs @@ -9,7 +9,7 @@ use tracing::error; use yazi_config::Priority; use yazi_fs::{FilesOp, SizeCalculator}; use yazi_plugin::isolate; -use yazi_shared::{Id, event::CmdCow, url::Url}; +use yazi_shared::{Id, event::CmdCow, url::UrlBuf}; use super::{PreworkIn, PreworkInFetch, PreworkInLoad, PreworkInSize}; use crate::{HIGH, NORMAL, TaskOp, TaskProg}; @@ -20,7 +20,7 @@ pub struct Prework { pub loaded: Mutex>, pub loading: Mutex>, - pub sizing: RwLock>, + pub sizing: RwLock>, } impl Prework { diff --git a/yazi-scheduler/src/process/in.rs b/yazi-scheduler/src/process/in.rs index 42ce8cfe..3af40ea7 100644 --- a/yazi-scheduler/src/process/in.rs +++ b/yazi-scheduler/src/process/in.rs @@ -1,7 +1,7 @@ use std::ffi::OsString; use tokio::sync::mpsc; -use yazi_shared::{Id, url::Url}; +use yazi_shared::{Id, url::UrlBuf}; use super::ShellOpt; @@ -9,7 +9,7 @@ use super::ShellOpt; #[derive(Debug)] pub struct ProcessInBlock { pub id: Id, - pub cwd: Url, + pub cwd: UrlBuf, pub cmd: OsString, pub args: Vec, } @@ -24,7 +24,7 @@ impl From for ShellOpt { #[derive(Debug)] pub struct ProcessInOrphan { pub id: Id, - pub cwd: Url, + pub cwd: UrlBuf, pub cmd: OsString, pub args: Vec, } @@ -39,7 +39,7 @@ impl From for ShellOpt { #[derive(Debug)] pub struct ProcessInBg { pub id: Id, - pub cwd: Url, + pub cwd: UrlBuf, pub cmd: OsString, pub args: Vec, pub cancel: mpsc::Receiver<()>, diff --git a/yazi-scheduler/src/process/shell.rs b/yazi-scheduler/src/process/shell.rs index 1f9a4153..1c61c01b 100644 --- a/yazi-scheduler/src/process/shell.rs +++ b/yazi-scheduler/src/process/shell.rs @@ -2,10 +2,10 @@ use std::{ffi::OsString, process::Stdio}; use anyhow::Result; use tokio::process::{Child, Command}; -use yazi_shared::url::Url; +use yazi_shared::url::UrlBuf; pub struct ShellOpt { - pub cwd: Url, + pub cwd: UrlBuf, pub cmd: OsString, pub args: Vec, pub piped: bool, diff --git a/yazi-scheduler/src/scheduler.rs b/yazi-scheduler/src/scheduler.rs index 8993831a..7a5355d9 100644 --- a/yazi-scheduler/src/scheduler.rs +++ b/yazi-scheduler/src/scheduler.rs @@ -9,7 +9,7 @@ use yazi_dds::Pump; use yazi_fs::{must_be_dir, path::unique_name, provider, remove_dir_clean}; use yazi_parser::{app::PluginOpt, tasks::ProcessExecOpt}; use yazi_proxy::MgrProxy; -use yazi_shared::{Id, Throttle, url::Url}; +use yazi_shared::{Id, Throttle, url::UrlBuf}; use super::{Ongoing, TaskProg, TaskStage}; use crate::{HIGH, LOW, NORMAL, TaskKind, TaskOp, file::{File, FileInDelete, FileInHardlink, FileInLink, FileInPaste, FileInTrash}, plugin::{Plugin, PluginInEntry}, prework::{Prework, PreworkInFetch, PreworkInLoad, PreworkInSize}, process::{Process, ProcessInBg, ProcessInBlock, ProcessInOrphan}}; @@ -73,7 +73,7 @@ impl Scheduler { } } - pub fn file_cut(&self, from: Url, mut to: Url, force: bool) { + pub fn file_cut(&self, from: UrlBuf, mut to: UrlBuf, force: bool) { let mut ongoing = self.ongoing.lock(); let id = ongoing.add(TaskKind::User, format!("Cut {} to {}", from.display(), to.display())); @@ -104,7 +104,7 @@ impl Scheduler { }); } - pub fn file_copy(&self, from: Url, mut to: Url, force: bool, follow: bool) { + pub fn file_copy(&self, from: UrlBuf, mut to: UrlBuf, force: bool, follow: bool) { let id = self .ongoing .lock() @@ -124,7 +124,7 @@ impl Scheduler { }); } - pub fn file_link(&self, from: Url, mut to: Url, relative: bool, force: bool) { + pub fn file_link(&self, from: UrlBuf, mut to: UrlBuf, relative: bool, force: bool) { let id = self .ongoing .lock() @@ -141,7 +141,7 @@ impl Scheduler { }); } - pub fn file_hardlink(&self, from: Url, mut to: Url, force: bool, follow: bool) { + pub fn file_hardlink(&self, from: UrlBuf, mut to: UrlBuf, force: bool, follow: bool) { let id = self .ongoing .lock() @@ -161,7 +161,7 @@ impl Scheduler { }); } - pub fn file_delete(&self, target: Url) { + pub fn file_delete(&self, target: UrlBuf) { let mut ongoing = self.ongoing.lock(); let id = ongoing.add(TaskKind::User, format!("Delete {}", target.display())); @@ -187,7 +187,7 @@ impl Scheduler { ); } - pub fn file_trash(&self, target: Url) { + pub fn file_trash(&self, target: UrlBuf) { let mut ongoing = self.ongoing.lock(); let id = ongoing.add(TaskKind::User, format!("Trash {}", target.display())); @@ -246,7 +246,7 @@ impl Scheduler { }); } - pub fn prework_size(&self, targets: Vec<&Url>) { + pub fn prework_size(&self, targets: Vec<&UrlBuf>) { let throttle = Arc::new(Throttle::new(targets.len(), Duration::from_millis(300))); let mut ongoing = self.ongoing.lock(); diff --git a/yazi-shared/src/event/cmd.rs b/yazi-shared/src/event/cmd.rs index db5587a1..c4bd739b 100644 --- a/yazi-shared/src/event/cmd.rs +++ b/yazi-shared/src/event/cmd.rs @@ -4,7 +4,7 @@ use anyhow::{Result, anyhow, bail}; use serde::{Deserialize, de}; use super::{Data, DataKey}; -use crate::{Id, Layer, SStr, Source, url::Url}; +use crate::{Id, Layer, SStr, Source, url::UrlBuf}; #[derive(Debug, Default)] pub struct Cmd { @@ -131,7 +131,7 @@ impl Cmd { } #[inline] - pub fn take_first_url(&mut self) -> Option { self.take_first()?.into_url() } + pub fn take_first_url(&mut self) -> Option { self.take_first()?.into_url() } #[inline] pub fn take_any(&mut self, name: impl Into) -> Option { diff --git a/yazi-shared/src/event/cow.rs b/yazi-shared/src/event/cow.rs index be2b2b1a..277944a6 100644 --- a/yazi-shared/src/event/cow.rs +++ b/yazi-shared/src/event/cow.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, ops::Deref}; use anyhow::Result; use super::{Cmd, Data, DataKey}; -use crate::{SStr, url::Url}; +use crate::{SStr, url::UrlBuf}; #[derive(Debug)] pub enum CmdCow { @@ -48,7 +48,7 @@ impl CmdCow { } #[inline] - pub fn take_url(&mut self, name: impl Into) -> Option { + pub fn take_url(&mut self, name: impl Into) -> Option { match self { Self::Owned(c) => c.take(name).and_then(Data::into_url), Self::Borrowed(c) => c.get(name).and_then(Data::to_url), @@ -63,7 +63,7 @@ impl CmdCow { } } - pub fn take_first_url(&mut self) -> Option { + pub fn take_first_url(&mut self) -> Option { match self { Self::Owned(c) => c.take_first_url(), Self::Borrowed(c) => c.first().and_then(Data::to_url), diff --git a/yazi-shared/src/event/data.rs b/yazi-shared/src/event/data.rs index 89e9b8f4..64dfff88 100644 --- a/yazi-shared/src/event/data.rs +++ b/yazi-shared/src/event/data.rs @@ -4,7 +4,7 @@ use anyhow::{Result, bail}; use ordered_float::OrderedFloat; use serde::{Deserialize, Serialize, de}; -use crate::{Id, SStr, url::{Url, UrnBuf}}; +use crate::{Id, SStr, url::{UrlBuf, UrnBuf}}; // --- Data #[derive(Debug, Serialize, Deserialize)] @@ -19,7 +19,7 @@ pub enum Data { Dict(HashMap), Id(Id), #[serde(skip_deserializing)] - Url(Url), + Url(UrlBuf), #[serde(skip_deserializing)] Urn(UrnBuf), #[serde(skip)] @@ -64,7 +64,7 @@ impl Data { } #[inline] - pub fn into_url(self) -> Option { + pub fn into_url(self) -> Option { match self { Self::String(s) => s.parse().ok(), Self::Url(u) => Some(u), @@ -94,7 +94,7 @@ impl Data { } #[inline] - pub fn to_url(&self) -> Option { + pub fn to_url(&self) -> Option { match self { Self::String(s) => s.parse().ok(), Self::Url(u) => Some(u.clone()), @@ -140,8 +140,8 @@ impl From for Data { fn from(value: Id) -> Self { Self::Id(value) } } -impl From<&Url> for Data { - fn from(value: &Url) -> Self { Self::Url(value.clone()) } +impl From<&UrlBuf> for Data { + fn from(value: &UrlBuf) -> Self { Self::Url(value.clone()) } } impl From<&str> for Data { @@ -164,7 +164,7 @@ pub enum DataKey { String(SStr), Id(Id), #[serde(skip_deserializing)] - Url(Url), + Url(UrlBuf), #[serde(skip_deserializing)] Urn(UrnBuf), #[serde(skip)] @@ -184,7 +184,7 @@ impl DataKey { } #[inline] - pub fn into_url(self) -> Option { + pub fn into_url(self) -> Option { match self { Self::String(s) => s.parse().ok(), Self::Url(u) => Some(u), diff --git a/yazi-shared/src/lib.rs b/yazi-shared/src/lib.rs index 9f4447af..a2632381 100644 --- a/yazi-shared/src/lib.rs +++ b/yazi-shared/src/lib.rs @@ -1,6 +1,6 @@ #![allow(clippy::option_map_unit_fn)] -yazi_macro::mod_pub!(errors event shell translit url); +yazi_macro::mod_pub!(errors event loc shell translit url); yazi_macro::mod_flat!(alias bytes chars condition debounce either env id layer natsort os osstr rand ro_cell source string sync_cell terminal throttle time utf8); diff --git a/yazi-shared/src/url/loc.rs b/yazi-shared/src/loc/buf.rs similarity index 64% rename from yazi-shared/src/url/loc.rs rename to yazi-shared/src/loc/buf.rs index ff761e68..4eee9d95 100644 --- a/yazi-shared/src/url/loc.rs +++ b/yazi-shared/src/loc/buf.rs @@ -1,47 +1,45 @@ -use std::{borrow::Cow, cmp, ffi::{OsStr, OsString}, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, mem, ops::Deref, path::{Path, PathBuf}}; +use std::{cmp, ffi::{OsStr, OsString}, fmt::{self, Debug, Formatter}, hash::{Hash, Hasher}, mem, ops::Deref, path::{Path, PathBuf}}; -use anyhow::{Result, bail}; +use anyhow::Result; -use crate::url::{Uri, Urn, UrnBuf}; +use crate::{loc::Loc, url::{Uri, Urn, UrnBuf}}; -#[derive(Clone, Default)] -pub struct Loc { - inner: PathBuf, - uri: usize, - urn: usize, +#[derive(Clone, Default, Eq)] +pub struct LocBuf { + pub(super) inner: PathBuf, + pub(super) uri: usize, + pub(super) urn: usize, } -impl Deref for Loc { +impl Deref for LocBuf { type Target = PathBuf; fn deref(&self) -> &Self::Target { &self.inner } } -impl AsRef for Loc { +impl AsRef for LocBuf { fn as_ref(&self) -> &Path { &self.inner } } -impl PartialEq for Loc { +impl PartialEq for LocBuf { fn eq(&self, other: &Self) -> bool { self.inner == other.inner } } -impl Eq for Loc {} - -impl Ord for Loc { +impl Ord for LocBuf { fn cmp(&self, other: &Self) -> cmp::Ordering { self.inner.cmp(&other.inner) } } -impl PartialOrd for Loc { +impl PartialOrd for LocBuf { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Hash for Loc { +impl Hash for LocBuf { fn hash(&self, state: &mut H) { self.inner.hash(state) } } -impl Debug for Loc { +impl Debug for LocBuf { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.debug_struct("Loc") + f.debug_struct("LocBuf") .field("path", &self.inner) .field("uri", &self.uri()) .field("urn", &self.urn()) @@ -49,84 +47,40 @@ impl Debug for Loc { } } -impl From for Loc { - fn from(value: OsString) -> Self { Self::from(PathBuf::from(value)) } -} - -impl From for Loc { - fn from(value: String) -> Self { Self::from(PathBuf::from(value)) } -} - -impl From for Loc { +impl From for LocBuf { fn from(path: PathBuf) -> Self { - let Some(name) = path.file_name() else { - let uri = path.as_os_str().len(); - return Self { inner: path, uri, urn: 0 }; - }; - - let name_len = name.len(); - let prefix_len = unsafe { - name - .as_encoded_bytes() - .as_ptr() - .offset_from_unsigned(path.as_os_str().as_encoded_bytes().as_ptr()) - }; + let Loc { inner, uri, urn } = Loc::from(path.as_path()); + let len = inner.as_os_str().len(); let mut bytes = path.into_os_string().into_encoded_bytes(); - bytes.truncate(prefix_len + name_len); + bytes.truncate(len); Self { inner: PathBuf::from(unsafe { OsString::from_encoded_bytes_unchecked(bytes) }), - uri: name_len, - urn: name_len, + uri, + urn, } } } -impl From> for Loc { - fn from(value: Cow<'_, Path>) -> Self { Self::from(value.into_owned()) } +impl> From<&T> for LocBuf { + fn from(value: &T) -> Self { Self::from(PathBuf::from(value)) } } -impl> From<&T> for Loc { - fn from(value: &T) -> Self { Self::from(value.as_ref().to_os_string()) } -} - -impl Loc { +impl LocBuf { pub fn new(path: impl Into, base: &Path, trail: &Path) -> Self { - let mut loc = Self::from(path.into()); - loc.uri = - loc.inner.strip_prefix(base).expect("Loc must start with the given base").as_os_str().len(); - loc.urn = - loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").as_os_str().len(); - loc + let loc = Self::from(path.into()); + let Loc { inner, uri, urn } = Loc::new(&loc.inner, base, trail); + + debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + Self { inner: loc.inner, uri, urn } } pub fn with(path: PathBuf, uri: usize, urn: usize) -> Result { - if urn > uri { - bail!("URN cannot be longer than URI"); - } + let loc = Self::from(path); + let Loc { inner, uri, urn } = Loc::with(&loc.inner, uri, urn)?; - let mut loc = Self::from(path); - if uri == 0 { - (loc.uri, loc.urn) = (0, 0); - return Ok(loc); - } else if urn == 0 { - loc.urn = 0; - } - - let mut it = loc.inner.components(); - for i in 1..=uri { - if it.next_back().is_none() { - bail!("URI exceeds the entire URL"); - } - if i == urn { - loc.urn = loc.strip_prefix(it.clone()).unwrap().as_os_str().len(); - } - if i == uri { - loc.uri = loc.strip_prefix(it).unwrap().as_os_str().len(); - break; - } - } - Ok(loc) + debug_assert!(inner.as_os_str() == loc.inner.as_os_str()); + Ok(Self { inner: loc.inner, uri, urn }) } pub fn zeroed(path: impl Into) -> Self { @@ -143,28 +97,13 @@ impl Loc { } #[inline] - pub fn uri(&self) -> &Uri { - Uri::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(self.bytes().len() - self.uri..), - ) - }) - } + pub fn as_loc<'a>(&'a self) -> Loc<'a> { Loc::from(self) } #[inline] - pub fn urn(&self) -> &Urn { - Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(self.bytes().len() - self.urn..), - ) - }) - } + pub fn to_path(&self) -> PathBuf { self.inner.clone() } #[inline] - pub fn urn_owned(&self) -> UrnBuf { self.urn().to_owned() } - - #[inline] - pub fn name(&self) -> &OsStr { self.inner.file_name().unwrap_or(OsStr::new("")) } + pub fn into_path(self) -> PathBuf { self.inner } pub fn set_name(&mut self, name: impl AsRef) { let old = self.bytes().len(); @@ -191,15 +130,6 @@ impl Loc { } } - #[inline] - pub fn base(&self) -> &Urn { - Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(..self.bytes().len() - self.uri), - ) - }) - } - #[inline] pub fn rebase(&self, base: &Path) -> Self { let mut loc: Self = base.join(self.uri()).into(); @@ -207,27 +137,6 @@ impl Loc { loc } - #[inline] - pub fn has_base(&self) -> bool { self.bytes().len() != self.uri } - - #[inline] - pub fn trail(&self) -> &Urn { - Urn::new(unsafe { - OsStr::from_encoded_bytes_unchecked( - self.bytes().get_unchecked(..self.bytes().len() - self.urn), - ) - }) - } - - #[inline] - pub fn has_trail(&self) -> bool { self.bytes().len() != self.urn } - - #[inline] - pub fn to_path(&self) -> PathBuf { self.inner.clone() } - - #[inline] - pub fn into_path(self) -> PathBuf { self.inner } - #[inline] pub fn triple(&self) -> (&Path, &Path, &Path) { let len = self.bytes().len(); @@ -256,28 +165,55 @@ impl Loc { } } +// FIXME: macro +impl LocBuf { + #[inline] + pub fn uri(&self) -> &Uri { self.as_loc().uri() } + + #[inline] + pub fn urn(&self) -> &Urn { self.as_loc().urn() } + + #[inline] + pub fn urn_owned(&self) -> UrnBuf { self.urn().to_owned() } + + #[inline] + pub fn base(&self) -> &Urn { self.as_loc().base() } + + #[inline] + pub fn has_base(&self) -> bool { self.as_loc().has_base() } + + #[inline] + pub fn trail(&self) -> &Urn { self.as_loc().trail() } + + #[inline] + pub fn has_trail(&self) -> bool { self.as_loc().has_trail() } + + #[inline] + pub fn name(&self) -> &OsStr { self.as_loc().name() } +} + #[cfg(test)] mod tests { use super::*; - use crate::url::Url; + use crate::url::UrlBuf; #[test] fn test_new() { - let loc: Loc = Path::new("/").into(); + let loc: LocBuf = Path::new("/").into(); assert_eq!(loc.uri().as_os_str(), OsStr::new("/")); assert_eq!(loc.urn().as_os_str(), OsStr::new("")); assert_eq!(loc.name(), OsStr::new("")); assert_eq!(loc.base().as_os_str(), OsStr::new("")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/")); - let loc: Loc = Path::new("/root").into(); + let loc: LocBuf = Path::new("/root").into(); assert_eq!(loc.uri().as_os_str(), OsStr::new("root")); assert_eq!(loc.urn().as_os_str(), OsStr::new("root")); assert_eq!(loc.name(), OsStr::new("root")); assert_eq!(loc.base().as_os_str(), OsStr::new("/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/")); - let loc: Loc = Path::new("/root/code/foo/").into(); + let loc: LocBuf = Path::new("/root/code/foo/").into(); assert_eq!(loc.uri().as_os_str(), OsStr::new("foo")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo")); assert_eq!(loc.name(), OsStr::new("foo")); @@ -287,42 +223,42 @@ mod tests { #[test] fn test_with() -> Result<()> { - let loc = Loc::with("/".into(), 0, 0)?; + let loc = LocBuf::with("/".into(), 0, 0)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("")); assert_eq!(loc.urn().as_os_str(), OsStr::new("")); assert_eq!(loc.name(), OsStr::new("")); assert_eq!(loc.base().as_os_str(), OsStr::new("/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/")); - let loc = Loc::with("/root/code/".into(), 1, 1)?; + let loc = LocBuf::with("/root/code/".into(), 1, 1)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code")); assert_eq!(loc.urn().as_os_str(), OsStr::new("code")); assert_eq!(loc.name(), OsStr::new("code")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/")); - let loc = Loc::with("/root/code/foo//".into(), 2, 1)?; + let loc = LocBuf::with("/root/code/foo//".into(), 2, 1)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo")); assert_eq!(loc.name(), OsStr::new("foo")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/code/")); - let loc = Loc::with("/root/code/foo//".into(), 2, 2)?; + let loc = LocBuf::with("/root/code/foo//".into(), 2, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.urn().as_os_str(), OsStr::new("code/foo")); assert_eq!(loc.name(), OsStr::new("foo")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/")); - let loc = Loc::with("/root/code/foo//bar/".into(), 2, 2)?; + let loc = LocBuf::with("/root/code/foo//bar/".into(), 2, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.name(), OsStr::new("bar")); assert_eq!(loc.base().as_os_str(), OsStr::new("/root/code/")); assert_eq!(loc.trail().as_os_str(), OsStr::new("/root/code/")); - let loc = Loc::with("/root/code/foo//bar/".into(), 3, 2)?; + let loc = LocBuf::with("/root/code/foo//bar/".into(), 3, 2)?; assert_eq!(loc.uri().as_os_str(), OsStr::new("code/foo//bar")); assert_eq!(loc.urn().as_os_str(), OsStr::new("foo//bar")); assert_eq!(loc.name(), OsStr::new("bar")); @@ -352,8 +288,8 @@ mod tests { ]; for (input, name, expected) in cases { - let mut a: Url = input.parse()?; - let b: Url = expected.parse()?; + let mut a: UrlBuf = input.parse()?; + let b: UrlBuf = expected.parse()?; a.set_name(name); assert_eq!( (a.name(), format!("{a:?}").replace(r"\", "/")), diff --git a/yazi-shared/src/loc/loc.rs b/yazi-shared/src/loc/loc.rs new file mode 100644 index 00000000..f214a62b --- /dev/null +++ b/yazi-shared/src/loc/loc.rs @@ -0,0 +1,147 @@ +use std::{ffi::OsStr, ops::Deref, path::Path}; + +use anyhow::{Result, bail}; + +use crate::{loc::LocBuf, url::{Uri, Urn}}; + +pub struct Loc<'a> { + pub(super) inner: &'a Path, + pub(super) uri: usize, + pub(super) urn: usize, +} + +impl Deref for Loc<'_> { + type Target = Path; + + fn deref(&self) -> &Self::Target { self.inner } +} + +impl<'a> From<&'a LocBuf> for Loc<'a> { + fn from(value: &'a LocBuf) -> Self { + Self { inner: &value.inner, uri: value.uri, urn: value.urn } + } +} + +impl<'a, T: ?Sized + AsRef> From<&'a T> for Loc<'a> { + fn from(value: &'a T) -> Self { + let path = Path::new(value.as_ref()); + let Some(name) = path.file_name() else { + let uri = path.as_os_str().len(); + return Self { inner: path, uri, urn: 0 }; + }; + + let name_len = name.len(); + let prefix_len = unsafe { + name + .as_encoded_bytes() + .as_ptr() + .offset_from_unsigned(path.as_os_str().as_encoded_bytes().as_ptr()) + }; + + let bytes = path.as_os_str().as_encoded_bytes(); + Self { + inner: Path::new(unsafe { + OsStr::from_encoded_bytes_unchecked(&bytes[..prefix_len + name_len]) + }), + uri: name_len, + urn: name_len, + } + } +} + +impl From> for LocBuf { + fn from(value: Loc<'_>) -> Self { + Self { inner: value.inner.to_owned(), uri: value.uri, urn: value.urn } + } +} + +impl<'a> Loc<'a> { + pub fn new(path: &'a T, base: &Path, trail: &Path) -> Self + where + T: AsRef + ?Sized, + { + let mut loc = Self::from(path.as_ref()); + loc.uri = + loc.inner.strip_prefix(base).expect("Loc must start with the given base").as_os_str().len(); + loc.urn = + loc.inner.strip_prefix(trail).expect("Loc must start with the given trail").as_os_str().len(); + loc + } + + pub fn with(path: &'a Path, uri: usize, urn: usize) -> Result { + if urn > uri { + bail!("URN cannot be longer than URI"); + } + + let mut loc = Self::from(path); + if uri == 0 { + (loc.uri, loc.urn) = (0, 0); + return Ok(loc); + } else if urn == 0 { + loc.urn = 0; + } + + let mut it = loc.inner.components(); + for i in 1..=uri { + if it.next_back().is_none() { + bail!("URI exceeds the entire URL"); + } + if i == urn { + loc.urn = loc.strip_prefix(it.clone()).unwrap().as_os_str().len(); + } + if i == uri { + loc.uri = loc.strip_prefix(it).unwrap().as_os_str().len(); + break; + } + } + Ok(loc) + } + + #[inline] + pub fn uri(&self) -> &'a Uri { + Uri::new(unsafe { + OsStr::from_encoded_bytes_unchecked( + self.bytes().get_unchecked(self.bytes().len() - self.uri..), + ) + }) + } + + #[inline] + pub fn urn(&self) -> &'a Urn { + Urn::new(unsafe { + OsStr::from_encoded_bytes_unchecked( + self.bytes().get_unchecked(self.bytes().len() - self.urn..), + ) + }) + } + + #[inline] + pub fn base(&self) -> &'a Urn { + Urn::new(unsafe { + OsStr::from_encoded_bytes_unchecked( + self.bytes().get_unchecked(..self.bytes().len() - self.uri), + ) + }) + } + + #[inline] + pub fn has_base(&self) -> bool { self.bytes().len() != self.uri } + + #[inline] + pub fn trail(&self) -> &'a Urn { + Urn::new(unsafe { + OsStr::from_encoded_bytes_unchecked( + self.bytes().get_unchecked(..self.bytes().len() - self.urn), + ) + }) + } + + #[inline] + pub fn has_trail(&self) -> bool { self.bytes().len() != self.urn } + + #[inline] + pub fn name(&self) -> &'a OsStr { self.inner.file_name().unwrap_or(OsStr::new("")) } + + #[inline] + fn bytes(&self) -> &'a [u8] { self.inner.as_os_str().as_encoded_bytes() } +} diff --git a/yazi-shared/src/loc/mod.rs b/yazi-shared/src/loc/mod.rs new file mode 100644 index 00000000..d89a0329 --- /dev/null +++ b/yazi-shared/src/loc/mod.rs @@ -0,0 +1 @@ +yazi_macro::mod_flat!(buf loc); diff --git a/yazi-shared/src/string.rs b/yazi-shared/src/string.rs index 4e484e44..39a5e58b 100644 --- a/yazi-shared/src/string.rs +++ b/yazi-shared/src/string.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}}; -use crate::url::Url; +use crate::url::UrlBuf; pub trait IntoStringLossy { fn into_string_lossy(self) -> String; @@ -32,6 +32,6 @@ impl IntoStringLossy for Cow<'_, OsStr> { } } -impl IntoStringLossy for &Url { +impl IntoStringLossy for &UrlBuf { fn into_string_lossy(self) -> String { self.os_str().into_string_lossy() } } diff --git a/yazi-shared/src/url/buf.rs b/yazi-shared/src/url/buf.rs new file mode 100644 index 00000000..baee1f9d --- /dev/null +++ b/yazi-shared/src/url/buf.rs @@ -0,0 +1,416 @@ +use std::{borrow::Cow, ffi::OsStr, fmt::{Debug, Formatter}, hash::BuildHasher, ops::Deref, path::{Path, PathBuf}, str::FromStr}; + +use anyhow::Result; +use percent_encoding::percent_decode; +use serde::{Deserialize, Serialize}; + +use super::UrnBuf; +use crate::{IntoOsStr, loc::LocBuf, url::{Components, Display, Encode, EncodeTilded, Scheme, Url, Urn}}; + +#[derive(Clone, Default, Eq, Ord, PartialOrd, PartialEq, Hash)] +pub struct UrlBuf { + pub loc: LocBuf, + pub scheme: Scheme, +} + +impl Deref for UrlBuf { + type Target = LocBuf; + + fn deref(&self) -> &Self::Target { &self.loc } +} + +impl From for UrlBuf { + fn from(loc: LocBuf) -> Self { Self { loc, scheme: Scheme::Regular } } +} + +impl From for UrlBuf { + fn from(path: PathBuf) -> Self { LocBuf::from(path).into() } +} + +impl From<&UrlBuf> for UrlBuf { + fn from(url: &UrlBuf) -> Self { url.clone() } +} + +impl From<&PathBuf> for UrlBuf { + fn from(path: &PathBuf) -> Self { path.to_owned().into() } +} + +impl From<&Path> for UrlBuf { + fn from(path: &Path) -> Self { path.to_path_buf().into() } +} + +impl TryFrom<&[u8]> for UrlBuf { + type Error = anyhow::Error; + + fn try_from(bytes: &[u8]) -> Result { + let (scheme, path, port) = Self::parse(bytes)?; + + let loc = + if let Some((uri, urn)) = port { LocBuf::with(path, uri, urn)? } else { LocBuf::from(path) }; + + Ok(Self { loc, scheme }) + } +} + +impl FromStr for UrlBuf { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { s.as_bytes().try_into() } +} + +impl TryFrom for UrlBuf { + type Error = anyhow::Error; + + fn try_from(value: String) -> Result { value.as_bytes().try_into() } +} + +impl AsRef for UrlBuf { + fn as_ref(&self) -> &UrlBuf { self } +} + +// FIXME: remove +impl AsRef for UrlBuf { + fn as_ref(&self) -> &Path { &self.loc } +} + +impl<'a> From<&'a UrlBuf> for Cow<'a, UrlBuf> { + fn from(url: &'a UrlBuf) -> Self { Cow::Borrowed(url) } +} + +impl From for Cow<'_, UrlBuf> { + fn from(url: UrlBuf) -> Self { Cow::Owned(url) } +} + +impl From> for UrlBuf { + fn from(url: Cow<'_, UrlBuf>) -> Self { url.into_owned() } +} + +impl UrlBuf { + pub fn join(&self, path: impl AsRef) -> Self { + use Scheme as S; + + let join = self.loc.join(path); + + 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::Sftp(_) => join.into(), + }; + + Self { loc, scheme: self.scheme.clone() } + } + + #[inline] + pub fn components(&self) -> Components<'_> { Components::new(self) } + + #[inline] + pub fn covariant(&self, other: &Self) -> bool { + self.scheme.covariant(&other.scheme) && self.loc == other.loc + } + + #[inline] + pub fn display(&self) -> Display<'_> { Display::new(self) } + + #[inline] + pub fn os_str(&self) -> Cow<'_, OsStr> { self.components().os_str() } + + pub fn parent_url(&self) -> Option { + use Scheme as S; + + let parent = self.loc.parent()?; + let uri = self.loc.uri(); + + Some(match self.scheme { + // Regular + S::Regular => Self { loc: parent.into(), scheme: S::Regular }, + + // Search + S::Search(_) if uri.is_empty() => Self { loc: parent.into(), scheme: S::Regular }, + S::Search(_) => Self { + loc: LocBuf::new(parent, self.loc.base(), self.loc.base()), + scheme: self.scheme.clone(), + }, + + // Archive + S::Archive(_) if uri.is_empty() => Self { loc: parent.into(), scheme: S::Regular }, + S::Archive(_) if uri.nth(1).is_none() => { + Self { loc: LocBuf::zeroed(parent), scheme: self.scheme.clone() } + } + S::Archive(_) => { + Self { loc: LocBuf::floated(parent, self.loc.base()), scheme: self.scheme.clone() } + } + + // SFTP + S::Sftp(_) => Self { loc: parent.into(), scheme: self.scheme.clone() }, + }) + } + + pub fn strip_prefix(&self, base: impl AsRef) -> Option<&Urn> { + use Scheme as S; + + let base = base.as_ref(); + let prefix = self.loc.strip_prefix(&base.loc).ok()?; + + Some(Urn::new(match (&self.scheme, &base.scheme) { + // Same scheme + (S::Regular, S::Regular) => Some(prefix), + (S::Search(_), S::Search(_)) => Some(prefix), + (S::Archive(a), S::Archive(b)) => Some(prefix).filter(|_| a == b), + (S::Sftp(a), S::Sftp(b)) => Some(prefix).filter(|_| a == b), + + // Both are local files + (S::Regular, S::Search(_)) => Some(prefix), + (S::Search(_), S::Regular) => Some(prefix), + + // Only the entry of archives is a local file + (S::Regular, S::Archive(_)) => Some(prefix).filter(|_| base.uri().is_empty()), + (S::Search(_), S::Archive(_)) => Some(prefix).filter(|_| base.uri().is_empty()), + (S::Archive(_), S::Regular) => Some(prefix).filter(|_| self.uri().is_empty()), + (S::Archive(_), S::Search(_)) => Some(prefix).filter(|_| self.uri().is_empty()), + + // Independent virtual file space + (S::Regular, S::Sftp(_)) => None, + (S::Search(_), S::Sftp(_)) => None, + (S::Archive(_), S::Sftp(_)) => None, + (S::Sftp(_), S::Regular) => None, + (S::Sftp(_), S::Search(_)) => None, + (S::Sftp(_), S::Archive(_)) => None, + }?)) + } + + #[inline] + pub fn as_path(&self) -> Option<&Path> { + Some(self.loc.as_path()).filter(|_| !self.scheme.is_virtual()) + } + + #[inline] + pub fn into_path(self) -> Option { + Some(self.loc.into_path()).filter(|_| !self.scheme.is_virtual()) + } + + #[inline] + pub fn set_name(&mut self, name: impl AsRef) { self.loc.set_name(name); } + + #[inline] + pub fn rebase(&self, base: &Path) -> Self { + Self { loc: self.loc.rebase(base), scheme: self.scheme.clone() } + } + + #[inline] + pub fn pair(&self) -> Option<(Self, UrnBuf)> { Some((self.parent_url()?, self.loc.urn_owned())) } + + #[inline] + pub fn hash_u64(&self) -> u64 { foldhash::fast::FixedState::default().hash_one(self) } + + pub fn parse(bytes: &[u8]) -> Result<(Scheme, PathBuf, Option<(usize, usize)>)> { + let mut skip = 0; + let (scheme, tilde, uri, urn) = Scheme::parse(bytes, &mut skip)?; + + let rest = if tilde { + Cow::from(percent_decode(&bytes[skip..])).into_os_str()? + } else { + bytes[skip..].into_os_str()? + }; + + let path = match rest { + Cow::Borrowed(s) => Path::new(s).to_owned(), + Cow::Owned(s) => PathBuf::from(s), + }; + + let ports = scheme.normalize_ports(uri, urn, &path)?; + + Ok((scheme, path, ports)) + } +} + +impl UrlBuf { + #[inline] + pub fn as_url(&self) -> Url<'_> { Url::from(self) } + + #[inline] + pub fn base(&self) -> Option> { self.as_url().base() } +} + +impl UrlBuf { + // --- Regular + #[inline] + pub fn is_regular(&self) -> bool { self.scheme == Scheme::Regular } + + #[inline] + pub fn to_regular(&self) -> Self { + Self { loc: self.loc.to_path().into(), scheme: Scheme::Regular } + } + + #[inline] + pub fn into_regular(mut self) -> Self { + self.loc = self.loc.into_path().into(); + self.scheme = Scheme::Regular; + self + } + + // --- Search + #[inline] + pub fn is_search(&self) -> bool { matches!(self.scheme, Scheme::Search(_)) } + + #[inline] + pub fn to_search(&self, domain: impl AsRef) -> Self { + Self { + loc: LocBuf::zeroed(self.loc.to_path()), + scheme: Scheme::Search(domain.as_ref().to_owned()), + } + } + + #[inline] + pub fn into_search(mut self, domain: impl AsRef) -> Self { + self.loc = LocBuf::zeroed(self.loc.into_path()); + self.scheme = Scheme::Search(domain.as_ref().to_owned()); + self + } + + // --- Archive + #[inline] + pub fn is_archive(&self) -> bool { matches!(self.scheme, Scheme::Archive(_)) } + + // --- Internal + #[inline] + pub fn is_internal(&self) -> bool { + match self.scheme { + Scheme::Regular | Scheme::Sftp(_) => true, + Scheme::Search(_) => !self.loc.uri().is_empty(), + Scheme::Archive(_) => false, + } + } + + // FIXME: remove + #[inline] + pub fn into_path2(self) -> PathBuf { self.loc.into_path() } +} + +impl Debug for UrlBuf { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}{}", Encode::from(self), self.loc.display()) + } +} + +impl Serialize for UrlBuf { + fn serialize(&self, serializer: S) -> Result { + let UrlBuf { scheme, loc } = self; + match (scheme.is_virtual(), loc.to_str()) { + (false, Some(s)) => serializer.serialize_str(s), + (true, Some(s)) => serializer.serialize_str(&format!("{}{s}", Encode::from(self))), + (_, None) => serializer.collect_str(&EncodeTilded::from(self)), + } + } +} + +impl<'de> Deserialize<'de> for UrlBuf { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Self::try_from(s).map_err(serde::de::Error::custom) + } +} + +// --- Tests +#[cfg(test)] +mod tests { + use anyhow::Result; + + use super::*; + + #[test] + fn test_join() -> anyhow::Result<()> { + let cases = [ + // Regular + ("/a", "b/c", "regular:///a/b/c"), + // Search + ("search://kw//a", "b/c", "search://kw:2:2//a/b/c"), + ("search://kw:2:2//a/b/c", "d/e", "search://kw:4:4//a/b/c/d/e"), + // Archive + ("archive:////a/b.zip", "c/d", "archive://:2:1//a/b.zip/c/d"), + ("archive://:2:1//a/b.zip/c/d", "e/f", "archive://:4:1//a/b.zip/c/d/e/f"), + ("archive://:2:2//a/b.zip/c/d", "e/f", "archive://:4:1//a/b.zip/c/d/e/f"), + // SFTP + ("sftp://remote//a", "b/c", "sftp://remote//a/b/c"), + ("sftp://remote:1:1//a/b/c", "d/e", "sftp://remote//a/b/c/d/e"), + // Relative + ("search://kw", "b/c", "search://kw:2:2/b/c"), + ("search://kw/", "b/c", "search://kw:2:2/b/c"), + ]; + + for (base, path, expected) in cases { + let base: UrlBuf = base.parse()?; + #[cfg(unix)] + assert_eq!(format!("{:?}", base.join(path)), expected); + #[cfg(windows)] + assert_eq!(format!("{:?}", base.join(path)).replace(r"\", "/"), expected.replace(r"\", "/")); + } + + Ok(()) + } + + #[test] + fn test_parent_url() -> anyhow::Result<()> { + let cases = [ + // Regular + ("/a", Some("regular:///")), + ("/", None), + // Search + ("search://kw:2:2//a/b/c", Some("search://kw:1:1//a/b")), + ("search://kw:1:1//a/b", Some("search://kw//a")), + ("search://kw//a", Some("regular:///")), + // Archive + ("archive://:2:1//a/b.zip/c/d", Some("archive://:1:1//a/b.zip/c")), + ("archive://:1:1//a/b.zip/c", Some("archive:////a/b.zip")), + ("archive:////a/b.zip", Some("regular:///a")), + // SFTP + ("sftp://remote:1:1//a/b", Some("sftp://remote//a")), + ("sftp://remote:1:1//a", Some("sftp://remote//")), + ("sftp://remote:1//", None), + ("sftp://remote//", None), + // Relative + ("search://kw:2:2/a/b", Some("search://kw:1:1/a")), + ("search://kw:1:1/a", Some("search://kw/")), + ("search://kw/", None), + ]; + + for (path, expected) in cases { + let path: UrlBuf = path.parse()?; + assert_eq!(path.parent_url().map(|u| format!("{:?}", u)).as_deref(), expected); + } + + Ok(()) + } + + #[test] + fn test_into_search() -> Result<()> { + const S: char = std::path::MAIN_SEPARATOR; + + let u: UrlBuf = "/root".parse()?; + assert_eq!(format!("{u:?}"), "regular:///root"); + + let u = u.into_search("kw"); + assert_eq!(format!("{u:?}"), "search://kw//root"); + assert_eq!(format!("{:?}", u.parent_url().unwrap()), "regular:///"); + + let u = u.join("examples"); + assert_eq!(format!("{u:?}"), format!("search://kw:1:1//root{S}examples")); + + let u = u.join("README.md"); + assert_eq!(format!("{u:?}"), format!("search://kw:2:2//root{S}examples{S}README.md")); + + let u = u.parent_url().unwrap(); + assert_eq!(format!("{u:?}"), format!("search://kw:1:1//root{S}examples")); + + let u = u.parent_url().unwrap(); + assert_eq!(format!("{u:?}"), "search://kw//root"); + + let u = u.parent_url().unwrap(); + assert_eq!(format!("{u:?}"), "regular:///"); + + Ok(()) + } +} diff --git a/yazi-shared/src/url/component.rs b/yazi-shared/src/url/component.rs index be7a5bf3..4dc19dbb 100644 --- a/yazi-shared/src/url/component.rs +++ b/yazi-shared/src/url/component.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}, iter::FusedIterator, ops::Not, path::{self, PathBuf, PrefixComponent}}; -use crate::url::{Encode, Loc, Scheme, Url}; +use crate::{loc::LocBuf, url::{Encode, Scheme, UrlBuf}}; #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum Component<'a> { @@ -24,7 +24,7 @@ impl<'a> From> for Component<'a> { } } -impl<'a> FromIterator> for Url { +impl<'a> FromIterator> for UrlBuf { fn from_iter>>(iter: I) -> Self { let mut scheme = Scheme::Regular; let mut buf = PathBuf::new(); @@ -60,13 +60,13 @@ impl<'a> FromIterator> for PathBuf { #[derive(Clone)] pub struct Components<'a> { inner: path::Components<'a>, - loc: &'a Loc, + loc: &'a LocBuf, scheme: &'a Scheme, scheme_yielded: bool, } impl<'a> Components<'a> { - pub fn new(url: &'a Url) -> Self { + pub fn new(url: &'a UrlBuf) -> Self { Self { inner: url.loc.components(), loc: &url.loc, @@ -149,7 +149,7 @@ mod tests { #[test] fn test_collect() { - let search: Url = "search://keyword//root/projects/yazi".parse().unwrap(); + let search: UrlBuf = "search://keyword//root/projects/yazi".parse().unwrap(); assert_eq!(search.loc.uri().as_os_str(), OsStr::new("")); assert_eq!(search.scheme, Scheme::Search("keyword".to_owned())); @@ -157,11 +157,11 @@ mod tests { assert_eq!(item.loc.uri().as_os_str(), OsStr::new("main.rs")); assert_eq!(item.scheme, Scheme::Search("keyword".to_owned())); - let u: Url = item.components().take(4).collect(); + let u: UrlBuf = item.components().take(4).collect(); assert_eq!(u.scheme, Scheme::Search("keyword".to_owned())); assert_eq!(u.loc.as_path(), Path::new("/root/projects")); - let u: Url = item + let u: UrlBuf = item .components() .take(5) .chain([Component::Normal(OsStr::new("target/release/yazi"))]) diff --git a/yazi-shared/src/url/cov.rs b/yazi-shared/src/url/cov.rs index 2f33f0a3..238e7e1e 100644 --- a/yazi-shared/src/url/cov.rs +++ b/yazi-shared/src/url/cov.rs @@ -2,31 +2,31 @@ use std::{hash::{Hash, Hasher}, ops::Deref}; use serde::{Deserialize, Serialize}; -use crate::url::Url; +use crate::url::UrlBuf; #[derive(Clone, Debug, Deserialize, Eq, Serialize)] #[repr(transparent)] -pub struct CovUrl(pub Url); +pub struct UrlCov(pub UrlBuf); -impl Deref for CovUrl { - type Target = Url; +impl Deref for UrlCov { + type Target = UrlBuf; fn deref(&self) -> &Self::Target { &self.0 } } -impl AsRef for CovUrl { - fn as_ref(&self) -> &Url { &self.0 } +impl AsRef for UrlCov { + fn as_ref(&self) -> &UrlBuf { &self.0 } } -impl From for CovUrl { - fn from(value: Url) -> Self { Self(value) } +impl From for UrlCov { + fn from(value: UrlBuf) -> Self { Self(value) } } -impl From for Url { - fn from(value: CovUrl) -> Self { value.0 } +impl From for UrlBuf { + fn from(value: UrlCov) -> Self { value.0 } } -impl Hash for CovUrl { +impl Hash for UrlCov { fn hash(&self, state: &mut H) { self.loc.hash(state); if self.scheme.is_virtual() { @@ -35,20 +35,20 @@ impl Hash for CovUrl { } } -impl PartialEq for CovUrl { +impl PartialEq for UrlCov { fn eq(&self, other: &Self) -> bool { self.covariant(other) } } -impl PartialEq for CovUrl { - fn eq(&self, other: &Url) -> bool { self.covariant(other) } +impl PartialEq for UrlCov { + fn eq(&self, other: &UrlBuf) -> bool { self.covariant(other) } } -impl CovUrl { +impl UrlCov { #[inline] - pub fn new>(u: &T) -> &Self { - unsafe { &*(u.as_ref() as *const Url as *const Self) } + pub fn new>(u: &T) -> &Self { + unsafe { &*(u.as_ref() as *const UrlBuf as *const Self) } } #[inline] - pub fn parent_url(&self) -> Option { self.0.parent_url().map(CovUrl) } + pub fn parent_url(&self) -> Option { self.0.parent_url().map(UrlCov) } } diff --git a/yazi-shared/src/url/display.rs b/yazi-shared/src/url/display.rs index 92ef33ac..6b99dd9b 100644 --- a/yazi-shared/src/url/display.rs +++ b/yazi-shared/src/url/display.rs @@ -1,17 +1,17 @@ -use crate::url::{Encode, Url}; +use crate::url::{Encode, UrlBuf}; pub struct Display<'a> { - inner: &'a Url, + inner: &'a UrlBuf, } impl<'a> Display<'a> { #[inline] - pub fn new(inner: &'a Url) -> Self { Self { inner } } + pub fn new(inner: &'a UrlBuf) -> Self { Self { inner } } } impl<'a> std::fmt::Display for Display<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Url { loc, scheme } = self.inner; + let UrlBuf { loc, scheme } = self.inner; if scheme.is_virtual() { Encode::from(self.inner).fmt(f)?; } diff --git a/yazi-shared/src/url/encode.rs b/yazi-shared/src/url/encode.rs index ae8a1d36..8416d922 100644 --- a/yazi-shared/src/url/encode.rs +++ b/yazi-shared/src/url/encode.rs @@ -2,20 +2,20 @@ use std::{fmt::{self, Display}, ops::Not}; use percent_encoding::{AsciiSet, CONTROLS, PercentEncode, percent_encode}; -use crate::url::{Loc, Scheme, Url}; +use crate::{loc::LocBuf, url::{Scheme, UrlBuf}}; pub struct Encode<'a> { - loc: &'a Loc, + loc: &'a LocBuf, scheme: &'a Scheme, } -impl<'a> From<&'a Url> for Encode<'a> { - fn from(url: &'a Url) -> Self { Self::new(&url.loc, &url.scheme) } +impl<'a> From<&'a UrlBuf> for Encode<'a> { + fn from(url: &'a UrlBuf) -> Self { Self::new(&url.loc, &url.scheme) } } impl<'a> Encode<'a> { #[inline] - pub(super) fn new(loc: &'a Loc, scheme: &'a Scheme) -> Self { Self { loc, scheme } } + pub(super) fn new(loc: &'a LocBuf, scheme: &'a Scheme) -> Self { Self { loc, scheme } } #[inline] fn domain<'s>(s: &'s str) -> PercentEncode<'s> { @@ -69,12 +69,12 @@ impl Display for Encode<'_> { // --- Tilded pub struct EncodeTilded<'a> { - loc: &'a Loc, + loc: &'a LocBuf, scheme: &'a Scheme, } -impl<'a> From<&'a Url> for EncodeTilded<'a> { - fn from(url: &'a Url) -> Self { Self { loc: &url.loc, scheme: &url.scheme } } +impl<'a> From<&'a UrlBuf> for EncodeTilded<'a> { + fn from(url: &'a UrlBuf) -> Self { Self { loc: &url.loc, scheme: &url.scheme } } } impl<'a> From<&'a EncodeTilded<'a>> for Encode<'a> { diff --git a/yazi-shared/src/url/mod.rs b/yazi-shared/src/url/mod.rs index edf2010b..3a71854e 100644 --- a/yazi-shared/src/url/mod.rs +++ b/yazi-shared/src/url/mod.rs @@ -1 +1 @@ -yazi_macro::mod_flat!(component cov display encode loc scheme uri url urn); +yazi_macro::mod_flat!(buf component cov display encode scheme uri url urn); diff --git a/yazi-shared/src/url/url.rs b/yazi-shared/src/url/url.rs index 6d163e1e..354a3edb 100644 --- a/yazi-shared/src/url/url.rs +++ b/yazi-shared/src/url/url.rs @@ -1,421 +1,36 @@ -use std::{borrow::Cow, ffi::OsStr, fmt::{Debug, Formatter}, hash::BuildHasher, ops::Deref, path::{Path, PathBuf}, str::FromStr}; +use std::path::Path; -use anyhow::Result; -use percent_encoding::percent_decode; -use serde::{Deserialize, Serialize}; +use crate::{loc::Loc, url::{Scheme, UrlBuf}}; -use super::UrnBuf; -use crate::{IntoOsStr, url::{Components, Display, Encode, EncodeTilded, Loc, Scheme, Urn}}; - -#[derive(Clone, Default, Eq, Ord, PartialOrd, PartialEq, Hash)] -pub struct Url { - pub loc: Loc, - pub scheme: Scheme, +pub struct Url<'a> { + pub loc: Loc<'a>, + pub scheme: &'a Scheme, } -impl Deref for Url { - type Target = Loc; - - fn deref(&self) -> &Self::Target { &self.loc } +impl<'a> From<&'a UrlBuf> for Url<'a> { + fn from(value: &'a UrlBuf) -> Self { Self { loc: value.loc.as_loc(), scheme: &value.scheme } } } -impl From for Url { - fn from(loc: Loc) -> Self { Self { loc, scheme: Scheme::Regular } } +impl From> for UrlBuf { + fn from(value: Url<'_>) -> Self { Self { loc: value.loc.into(), scheme: value.scheme.clone() } } } -impl From for Url { - fn from(path: PathBuf) -> Self { Loc::from(path).into() } -} +impl<'a> Url<'a> { + pub fn regular(path: &'a Path) -> Self { Self { loc: path.into(), scheme: &Scheme::Regular } } -impl From<&Url> for Url { - fn from(url: &Url) -> Self { url.clone() } -} - -impl From<&PathBuf> for Url { - fn from(path: &PathBuf) -> Self { path.to_owned().into() } -} - -impl From<&Path> for Url { - fn from(path: &Path) -> Self { path.to_path_buf().into() } -} - -impl TryFrom<&[u8]> for Url { - type Error = anyhow::Error; - - fn try_from(bytes: &[u8]) -> Result { - let (scheme, path, port) = Self::parse(bytes)?; - - let loc = - if let Some((uri, urn)) = port { Loc::with(path, uri, urn)? } else { Loc::from(path) }; - - Ok(Self { loc, scheme }) - } -} - -impl FromStr for Url { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { s.as_bytes().try_into() } -} - -impl TryFrom for Url { - type Error = anyhow::Error; - - fn try_from(value: String) -> Result { value.as_bytes().try_into() } -} - -impl AsRef for Url { - fn as_ref(&self) -> &Url { self } -} - -// FIXME: remove -impl AsRef for Url { - fn as_ref(&self) -> &Path { &self.loc } -} - -impl<'a> From<&'a Url> for Cow<'a, Url> { - fn from(url: &'a Url) -> Self { Cow::Borrowed(url) } -} - -impl From for Cow<'_, Url> { - fn from(url: Url) -> Self { Cow::Owned(url) } -} - -impl From> for Url { - fn from(url: Cow<'_, Url>) -> Self { url.into_owned() } -} - -impl Url { - #[inline] - pub fn base(&self) -> Url { + pub fn base(&self) -> Option { use Scheme as S; + if !self.loc.has_base() { + return None; + } + let loc: Loc = self.loc.base().into(); - match self.scheme { - S::Regular => Self { loc, scheme: S::Regular }, - S::Search(_) => Self { loc, scheme: self.scheme.clone() }, - S::Archive(_) => Self { loc, scheme: self.scheme.clone() }, - S::Sftp(_) => Self { loc, scheme: self.scheme.clone() }, - } - } - - pub fn join(&self, path: impl AsRef) -> Self { - use Scheme as S; - - let join = self.loc.join(path); - - let loc = match self.scheme { - S::Regular => join.into(), - S::Search(_) => Loc::new(join, self.loc.base(), self.loc.base()), - S::Archive(_) => Loc::floated(join, self.loc.base()), - S::Sftp(_) => join.into(), - }; - - Self { loc, scheme: self.scheme.clone() } - } - - #[inline] - pub fn components(&self) -> Components<'_> { Components::new(self) } - - #[inline] - pub fn covariant(&self, other: &Self) -> bool { - self.scheme.covariant(&other.scheme) && self.loc == other.loc - } - - #[inline] - pub fn display(&self) -> Display<'_> { Display::new(self) } - - #[inline] - pub fn os_str(&self) -> Cow<'_, OsStr> { self.components().os_str() } - - pub fn parent_url(&self) -> Option { - use Scheme as S; - - let parent = self.loc.parent()?; - let uri = self.loc.uri(); - Some(match self.scheme { - // Regular - S::Regular => Self { loc: parent.into(), scheme: S::Regular }, - - // Search - S::Search(_) if uri.is_empty() => Self { loc: parent.into(), scheme: S::Regular }, - S::Search(_) => Self { - loc: Loc::new(parent, self.loc.base(), self.loc.base()), - scheme: self.scheme.clone(), - }, - - // Archive - S::Archive(_) if uri.is_empty() => Self { loc: parent.into(), scheme: S::Regular }, - S::Archive(_) if uri.nth(1).is_none() => { - Self { loc: Loc::zeroed(parent), scheme: self.scheme.clone() } - } - S::Archive(_) => { - Self { loc: Loc::floated(parent, self.loc.base()), scheme: self.scheme.clone() } - } - - // SFTP - S::Sftp(_) => Self { loc: parent.into(), scheme: self.scheme.clone() }, + S::Regular => Self { loc, scheme: &S::Regular }, + S::Search(_) => Self { loc, scheme: &self.scheme }, + S::Archive(_) => Self { loc, scheme: &self.scheme }, + S::Sftp(_) => Self { loc, scheme: &self.scheme }, }) } - - pub fn strip_prefix(&self, base: impl AsRef) -> Option<&Urn> { - use Scheme as S; - - let base = base.as_ref(); - let prefix = self.loc.strip_prefix(&base.loc).ok()?; - - Some(Urn::new(match (&self.scheme, &base.scheme) { - // Same scheme - (S::Regular, S::Regular) => Some(prefix), - (S::Search(_), S::Search(_)) => Some(prefix), - (S::Archive(a), S::Archive(b)) => Some(prefix).filter(|_| a == b), - (S::Sftp(a), S::Sftp(b)) => Some(prefix).filter(|_| a == b), - - // Both are local files - (S::Regular, S::Search(_)) => Some(prefix), - (S::Search(_), S::Regular) => Some(prefix), - - // Only the entry of archives is a local file - (S::Regular, S::Archive(_)) => Some(prefix).filter(|_| base.uri().is_empty()), - (S::Search(_), S::Archive(_)) => Some(prefix).filter(|_| base.uri().is_empty()), - (S::Archive(_), S::Regular) => Some(prefix).filter(|_| self.uri().is_empty()), - (S::Archive(_), S::Search(_)) => Some(prefix).filter(|_| self.uri().is_empty()), - - // Independent virtual file space - (S::Regular, S::Sftp(_)) => None, - (S::Search(_), S::Sftp(_)) => None, - (S::Archive(_), S::Sftp(_)) => None, - (S::Sftp(_), S::Regular) => None, - (S::Sftp(_), S::Search(_)) => None, - (S::Sftp(_), S::Archive(_)) => None, - }?)) - } - - #[inline] - pub fn as_path(&self) -> Option<&Path> { - Some(self.loc.as_path()).filter(|_| !self.scheme.is_virtual()) - } - - #[inline] - pub fn into_path(self) -> Option { - Some(self.loc.into_path()).filter(|_| !self.scheme.is_virtual()) - } - - #[inline] - pub fn set_name(&mut self, name: impl AsRef) { self.loc.set_name(name); } - - #[inline] - pub fn rebase(&self, base: &Path) -> Self { - Self { loc: self.loc.rebase(base), scheme: self.scheme.clone() } - } - - #[inline] - pub fn pair(&self) -> Option<(Self, UrnBuf)> { Some((self.parent_url()?, self.loc.urn_owned())) } - - #[inline] - pub fn hash_u64(&self) -> u64 { foldhash::fast::FixedState::default().hash_one(self) } - - pub fn parse(bytes: &[u8]) -> Result<(Scheme, PathBuf, Option<(usize, usize)>)> { - let mut skip = 0; - let (scheme, tilde, uri, urn) = Scheme::parse(bytes, &mut skip)?; - - let rest = if tilde { - Cow::from(percent_decode(&bytes[skip..])).into_os_str()? - } else { - bytes[skip..].into_os_str()? - }; - - let path = match rest { - Cow::Borrowed(s) => Path::new(s).to_owned(), - Cow::Owned(s) => PathBuf::from(s), - }; - - let ports = scheme.normalize_ports(uri, urn, &path)?; - - Ok((scheme, path, ports)) - } -} - -impl Url { - // --- Regular - #[inline] - pub fn is_regular(&self) -> bool { self.scheme == Scheme::Regular } - - #[inline] - pub fn to_regular(&self) -> Self { - Self { loc: self.loc.to_path().into(), scheme: Scheme::Regular } - } - - #[inline] - pub fn into_regular(mut self) -> Self { - self.loc = self.loc.into_path().into(); - self.scheme = Scheme::Regular; - self - } - - // --- Search - #[inline] - pub fn is_search(&self) -> bool { matches!(self.scheme, Scheme::Search(_)) } - - #[inline] - pub fn to_search(&self, domain: impl AsRef) -> Self { - Self { - loc: Loc::zeroed(self.loc.to_path()), - scheme: Scheme::Search(domain.as_ref().to_owned()), - } - } - - #[inline] - pub fn into_search(mut self, domain: impl AsRef) -> Self { - self.loc = Loc::zeroed(self.loc.into_path()); - self.scheme = Scheme::Search(domain.as_ref().to_owned()); - self - } - - // --- Archive - #[inline] - pub fn is_archive(&self) -> bool { matches!(self.scheme, Scheme::Archive(_)) } - - // --- Internal - #[inline] - pub fn is_internal(&self) -> bool { - match self.scheme { - Scheme::Regular | Scheme::Sftp(_) => true, - Scheme::Search(_) => !self.loc.uri().is_empty(), - Scheme::Archive(_) => false, - } - } - - // FIXME: remove - #[inline] - pub fn into_path2(self) -> PathBuf { self.loc.into_path() } -} - -impl Debug for Url { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}{}", Encode::from(self), self.loc.display()) - } -} - -impl Serialize for Url { - fn serialize(&self, serializer: S) -> Result { - let Url { scheme, loc } = self; - match (scheme.is_virtual(), loc.to_str()) { - (false, Some(s)) => serializer.serialize_str(s), - (true, Some(s)) => serializer.serialize_str(&format!("{}{s}", Encode::from(self))), - (_, None) => serializer.collect_str(&EncodeTilded::from(self)), - } - } -} - -impl<'de> Deserialize<'de> for Url { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - Self::try_from(s).map_err(serde::de::Error::custom) - } -} - -// --- Tests -#[cfg(test)] -mod tests { - use anyhow::Result; - - use super::*; - - #[test] - fn test_join() -> anyhow::Result<()> { - let cases = [ - // Regular - ("/a", "b/c", "regular:///a/b/c"), - // Search - ("search://kw//a", "b/c", "search://kw:2:2//a/b/c"), - ("search://kw:2:2//a/b/c", "d/e", "search://kw:4:4//a/b/c/d/e"), - // Archive - ("archive:////a/b.zip", "c/d", "archive://:2:1//a/b.zip/c/d"), - ("archive://:2:1//a/b.zip/c/d", "e/f", "archive://:4:1//a/b.zip/c/d/e/f"), - ("archive://:2:2//a/b.zip/c/d", "e/f", "archive://:4:1//a/b.zip/c/d/e/f"), - // SFTP - ("sftp://remote//a", "b/c", "sftp://remote//a/b/c"), - ("sftp://remote:1:1//a/b/c", "d/e", "sftp://remote//a/b/c/d/e"), - // Relative - ("search://kw", "b/c", "search://kw:2:2/b/c"), - ("search://kw/", "b/c", "search://kw:2:2/b/c"), - ]; - - for (base, path, expected) in cases { - let base: Url = base.parse()?; - #[cfg(unix)] - assert_eq!(format!("{:?}", base.join(path)), expected); - #[cfg(windows)] - assert_eq!(format!("{:?}", base.join(path)).replace(r"\", "/"), expected.replace(r"\", "/")); - } - - Ok(()) - } - - #[test] - fn test_parent_url() -> anyhow::Result<()> { - let cases = [ - // Regular - ("/a", Some("regular:///")), - ("/", None), - // Search - ("search://kw:2:2//a/b/c", Some("search://kw:1:1//a/b")), - ("search://kw:1:1//a/b", Some("search://kw//a")), - ("search://kw//a", Some("regular:///")), - // Archive - ("archive://:2:1//a/b.zip/c/d", Some("archive://:1:1//a/b.zip/c")), - ("archive://:1:1//a/b.zip/c", Some("archive:////a/b.zip")), - ("archive:////a/b.zip", Some("regular:///a")), - // SFTP - ("sftp://remote:1:1//a/b", Some("sftp://remote//a")), - ("sftp://remote:1:1//a", Some("sftp://remote//")), - ("sftp://remote:1//", None), - ("sftp://remote//", None), - // Relative - ("search://kw:2:2/a/b", Some("search://kw:1:1/a")), - ("search://kw:1:1/a", Some("search://kw/")), - ("search://kw/", None), - ]; - - for (path, expected) in cases { - let path: Url = path.parse()?; - assert_eq!(path.parent_url().map(|u| format!("{:?}", u)).as_deref(), expected); - } - - Ok(()) - } - - #[test] - fn test_into_search() -> Result<()> { - const S: char = std::path::MAIN_SEPARATOR; - - let u: Url = "/root".parse()?; - assert_eq!(format!("{u:?}"), "regular:///root"); - - let u = u.into_search("kw"); - assert_eq!(format!("{u:?}"), "search://kw//root"); - assert_eq!(format!("{:?}", u.parent_url().unwrap()), "regular:///"); - - let u = u.join("examples"); - assert_eq!(format!("{u:?}"), format!("search://kw:1:1//root{S}examples")); - - let u = u.join("README.md"); - assert_eq!(format!("{u:?}"), format!("search://kw:2:2//root{S}examples{S}README.md")); - - let u = u.parent_url().unwrap(); - assert_eq!(format!("{u:?}"), format!("search://kw:1:1//root{S}examples")); - - let u = u.parent_url().unwrap(); - assert_eq!(format!("{u:?}"), "search://kw//root"); - - let u = u.parent_url().unwrap(); - assert_eq!(format!("{u:?}"), "regular:///"); - - Ok(()) - } }