Skip to main content

yazi_shared/url/
traits.rs

1use std::{hash::BuildHasher, path::{Path, PathBuf}};
2
3use hashbrown::{HashMap, hash_map::EntryRef};
4
5use crate::{loc::Loc, url::{Url, UrlBuf, UrlBufCov, UrlCov, UrlCow}};
6
7// --- AsUrl
8pub trait AsUrl {
9	fn as_url(&self) -> Url<'_>;
10}
11
12impl AsUrl for Path {
13	#[inline]
14	fn as_url(&self) -> Url<'_> { Url::Regular(Loc::bare(self)) }
15}
16
17impl AsUrl for &Path {
18	#[inline]
19	fn as_url(&self) -> Url<'_> { (*self).as_url() }
20}
21
22impl AsUrl for PathBuf {
23	#[inline]
24	fn as_url(&self) -> Url<'_> { self.as_path().as_url() }
25}
26
27impl AsUrl for &PathBuf {
28	#[inline]
29	fn as_url(&self) -> Url<'_> { (*self).as_path().as_url() }
30}
31
32impl AsUrl for Url<'_> {
33	#[inline]
34	fn as_url(&self) -> Url<'_> { *self }
35}
36
37impl AsUrl for UrlBuf {
38	#[inline]
39	fn as_url(&self) -> Url<'_> {
40		match self {
41			Self::Regular(loc) => Url::Regular(loc.as_loc()),
42			Self::Search { loc, domain } => Url::Search { loc: loc.as_loc(), domain },
43			Self::Archive { loc, domain } => Url::Archive { loc: loc.as_loc(), domain },
44			Self::Sftp { loc, domain } => Url::Sftp { loc: loc.as_loc(), domain },
45		}
46	}
47}
48
49impl AsUrl for &UrlBuf {
50	#[inline]
51	fn as_url(&self) -> Url<'_> { (**self).as_url() }
52}
53
54impl AsUrl for &mut UrlBuf {
55	#[inline]
56	fn as_url(&self) -> Url<'_> { (**self).as_url() }
57}
58
59impl AsUrl for UrlCow<'_> {
60	fn as_url(&self) -> Url<'_> {
61		match self {
62			Self::Regular(loc) => Url::Regular(loc.as_loc()),
63			Self::Search { loc, domain } => Url::Search { loc: loc.as_loc(), domain },
64			Self::Archive { loc, domain } => Url::Archive { loc: loc.as_loc(), domain },
65			Self::Sftp { loc, domain } => Url::Sftp { loc: loc.as_loc(), domain },
66		}
67	}
68}
69
70impl AsUrl for &UrlCow<'_> {
71	fn as_url(&self) -> Url<'_> { (**self).as_url() }
72}
73
74impl AsUrl for super::Components<'_> {
75	fn as_url(&self) -> Url<'_> { self.url() }
76}
77
78impl<'a, T> From<&'a T> for Url<'a>
79where
80	T: AsUrl + ?Sized,
81{
82	fn from(value: &'a T) -> Self { value.as_url() }
83}
84
85impl<'a, T> From<&'a mut T> for Url<'a>
86where
87	T: AsUrl + ?Sized,
88{
89	fn from(value: &'a mut T) -> Self { value.as_url() }
90}
91
92// --- UrlMapExt
93pub trait UrlMapExt<V> {
94	fn get_or_insert_default<U>(&mut self, url: U) -> &mut V
95	where
96		U: AsUrl,
97		V: Default;
98
99	fn get_or_insert_with<U, F>(&mut self, url: U, default: F) -> &mut V
100	where
101		U: AsUrl,
102		F: FnOnce(Url<'_>) -> V;
103}
104
105impl<V, S> UrlMapExt<V> for HashMap<UrlBuf, V, S>
106where
107	S: BuildHasher,
108{
109	fn get_or_insert_default<U>(&mut self, url: U) -> &mut V
110	where
111		U: AsUrl,
112		V: Default,
113	{
114		self.get_or_insert_with(url, |_| Default::default())
115	}
116
117	fn get_or_insert_with<U, F>(&mut self, url: U, default: F) -> &mut V
118	where
119		U: AsUrl,
120		F: FnOnce(Url<'_>) -> V,
121	{
122		let url = url.as_url();
123		match self.entry_ref(&url) {
124			EntryRef::Occupied(oe) => oe.into_mut(),
125			EntryRef::Vacant(ve) => ve.insert_with_key(url.into(), default(url)),
126		}
127	}
128}
129
130// --- UrlCovMapExt
131pub trait UrlCovMapExt<V> {
132	fn get_or_insert_default(&mut self, url: UrlCov<'_>) -> &mut V
133	where
134		V: Default;
135}
136
137impl<V, S> UrlCovMapExt<V> for HashMap<UrlBufCov, V, S>
138where
139	S: BuildHasher,
140{
141	fn get_or_insert_default(&mut self, url: UrlCov<'_>) -> &mut V
142	where
143		V: Default,
144	{
145		match self.entry_ref(&url) {
146			EntryRef::Occupied(oe) => oe.into_mut(),
147			EntryRef::Vacant(ve) => ve.insert_with_key(url.into(), Default::default()),
148		}
149	}
150}