use crate::host::Host;
use crate::parser::default_port;
use crate::Url;
use alloc::borrow::ToOwned;
use alloc::format;
use alloc::string::String;
use core::sync::atomic::{AtomicUsize, Ordering};
pub fn url_origin(url: &Url) -> Origin {
let scheme = url.scheme();
match scheme {
"blob" => {
let result = Url::parse(url.path());
match result {
Ok(ref url) => url_origin(url),
Err(_) => Origin::new_opaque(),
}
}
"ftp" | "http" | "https" | "ws" | "wss" => Origin::Tuple(
scheme.to_owned(),
url.host().unwrap().to_owned(),
url.port_or_known_default().unwrap(),
),
"file" => Origin::new_opaque(),
_ => Origin::new_opaque(),
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Origin {
Opaque(OpaqueOrigin),
Tuple(String, Host<String>, u16),
}
impl Origin {
pub fn new_opaque() -> Self {
static COUNTER: AtomicUsize = AtomicUsize::new(0);
Self::Opaque(OpaqueOrigin(COUNTER.fetch_add(1, Ordering::SeqCst)))
}
pub fn is_tuple(&self) -> bool {
matches!(*self, Self::Tuple(..))
}
pub fn ascii_serialization(&self) -> String {
match *self {
Self::Opaque(_) => "null".to_owned(),
Self::Tuple(ref scheme, ref host, port) => {
if default_port(scheme) == Some(port) {
format!("{scheme}://{host}")
} else {
format!("{scheme}://{host}:{port}")
}
}
}
}
pub fn unicode_serialization(&self) -> String {
match *self {
Self::Opaque(_) => "null".to_owned(),
Self::Tuple(ref scheme, ref host, port) => {
let host = match *host {
Host::Domain(ref domain) => {
let (domain, _errors) = idna::domain_to_unicode(domain);
Host::Domain(domain)
}
_ => host.clone(),
};
if default_port(scheme) == Some(port) {
format!("{scheme}://{host}")
} else {
format!("{scheme}://{host}:{port}")
}
}
}
}
}
#[derive(Eq, PartialEq, Hash, Clone, Debug)]
pub struct OpaqueOrigin(usize);