#![no_std]
extern crate alloc;
use alloc::string::String;
use core::fmt::Write;
macro_rules! impl_protocol {
( $($protocol:ident, $name:expr, $port:expr); * $(;)* ) => {
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Protocol {
$(
$protocol,
)+
Custom(String, u16)
}
impl Protocol{
pub fn get_default_from_str<S: AsRef<str>>(s: S) -> Option<Self>{
let s = s.as_ref();
$(
if s.eq_ignore_ascii_case($name) {
return Some(Protocol::$protocol);
}
)+
None
}
pub fn get_default_port(&self) -> u16 {
match self {
$(
Protocol::$protocol => $port,
)+
Protocol::Custom(_, port) => *port
}
}
pub fn get_name(&self) -> &str {
match self {
$(
Protocol::$protocol => $name,
)+
Protocol::Custom(name, _) => name
}
}
}
};
}
impl_protocol! {
HTTP, "http", 80;
HTTPS, "https", 443;
FTP, "ftp", 21;
WS, "ws", 80;
WSS, "wss", 443;
}
pub fn create_prefix(
protocol: Protocol,
domain: impl AsRef<str>,
port: Option<u16>,
path: Option<impl AsRef<str>>,
) -> String {
let protocol_name = protocol.get_name();
let domain = domain.as_ref();
let mut prefix = String::with_capacity(
protocol_name.len()
+ 3
+ domain.len()
+ 6
+ path.as_ref().map_or(0, |p| p.as_ref().len() + 1),
);
prefix.push_str(protocol_name);
prefix.push_str("://");
prefix.push_str(domain);
if let Some(port) = port {
if port != protocol.get_default_port() {
write!(prefix, ":{port}").unwrap();
}
}
if let Some(path) = path {
slash_formatter::concat_with_slash_in_place(&mut prefix, path.as_ref());
}
prefix
}