Skip to main content

yazi_shared/scheme/
encode.rs

1use std::fmt::{self, Display};
2
3use percent_encoding::{AsciiSet, CONTROLS, PercentEncode, percent_encode};
4
5use crate::{scheme::SchemeKind, url::Url};
6
7#[derive(Clone, Copy)]
8pub struct Encode<'a>(pub Url<'a>);
9
10impl<'a> From<crate::url::Encode<'a>> for Encode<'a> {
11	fn from(value: crate::url::Encode<'a>) -> Self { Self(value.0) }
12}
13
14impl<'a> Encode<'a> {
15	#[inline]
16	pub fn domain<'s>(s: &'s str) -> PercentEncode<'s> {
17		const SET: &AsciiSet = &CONTROLS.add(b'/').add(b':');
18		percent_encode(s.as_bytes(), SET)
19	}
20
21	pub(crate) fn ports(self) -> impl Display {
22		struct D<'a>(Encode<'a>);
23
24		impl Display for D<'_> {
25			fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26				macro_rules! w {
27					($default_uri:expr, $default_urn:expr) => {{
28						let (uri, urn) = self.0.0.scheme().ports();
29						match (uri != $default_uri, urn != $default_urn) {
30							(true, true) => write!(f, ":{uri}:{urn}"),
31							(true, false) => write!(f, ":{uri}"),
32							(false, true) => write!(f, "::{urn}"),
33							(false, false) => Ok(()),
34						}
35					}};
36				}
37
38				match self.0.0.kind() {
39					SchemeKind::Regular => Ok(()),
40					SchemeKind::Search | SchemeKind::Archive => w!(0, 0),
41					SchemeKind::Sftp => {
42						w!(self.0.0.loc().name().is_some() as usize, self.0.0.loc().name().is_some() as usize)
43					}
44				}
45			}
46		}
47
48		D(self)
49	}
50}
51
52impl Display for Encode<'_> {
53	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54		match self.0 {
55			Url::Regular(_) => write!(f, "regular://"),
56			Url::Search { domain, .. } => write!(f, "search://{}{}/", Self::domain(domain), self.ports()),
57			Url::Archive { domain, .. } => {
58				write!(f, "archive://{}{}/", Self::domain(domain), self.ports())
59			}
60			Url::Sftp { domain, .. } => write!(f, "sftp://{}{}/", Self::domain(domain), self.ports()),
61		}
62	}
63}