#[derive(Debug, Clone, PartialEq)]
pub struct SxurlHeader {
pub version: u16,
pub scheme: String,
pub sub_present: bool,
pub params_present: bool,
pub frag_present: bool,
pub port_present: bool,
}
impl SxurlHeader {
pub fn new(
scheme: String,
sub_present: bool,
params_present: bool,
frag_present: bool,
port_present: bool,
) -> Self {
Self {
version: 1,
scheme,
sub_present,
params_present,
frag_present,
port_present,
}
}
pub fn scheme_code(&self) -> u8 {
match self.scheme.as_str() {
"https" => 0,
"http" => 1,
"ftp" => 2,
_ => unreachable!("Invalid scheme should be caught during validation"),
}
}
pub fn scheme_from_code(code: u8) -> Option<String> {
match code {
0 => Some("https".to_string()),
1 => Some("http".to_string()),
2 => Some("ftp".to_string()),
_ => None,
}
}
pub fn pack_flags(&self) -> u16 {
let mut flags = 0u16;
if self.sub_present {
flags |= 1 << 0;
}
if self.params_present {
flags |= 1 << 1;
}
if self.frag_present {
flags |= 1 << 2;
}
if self.port_present {
flags |= 1 << 3;
}
flags
}
pub fn unpack_flags(flags: u16) -> (bool, bool, bool, bool) {
let sub_present = (flags & (1 << 0)) != 0;
let params_present = (flags & (1 << 1)) != 0;
let frag_present = (flags & (1 << 2)) != 0;
let port_present = (flags & (1 << 3)) != 0;
(sub_present, params_present, frag_present, port_present)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct UrlComponents {
pub scheme: String,
pub tld: String,
pub domain: String,
pub subdomain: String,
pub port: u16,
pub path: String,
pub query: String,
pub fragment: String,
}
impl UrlComponents {
pub fn new(
scheme: String,
tld: String,
domain: String,
subdomain: String,
port: u16,
path: String,
query: String,
fragment: String,
) -> Self {
Self {
scheme,
tld,
domain,
subdomain,
port,
path,
query,
fragment,
}
}
pub fn has_subdomain(&self) -> bool {
!self.subdomain.is_empty()
}
pub fn has_params(&self) -> bool {
!self.query.is_empty()
}
pub fn has_fragment(&self) -> bool {
!self.fragment.is_empty()
}
pub fn has_port(&self) -> bool {
self.port != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UrlComponentType {
Scheme,
Host,
Domain,
Subdomain,
Tld,
Port,
Path,
Query,
Fragment,
PathSegments,
Filename,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sxurl_header_creation() {
let header = SxurlHeader::new(
"https".to_string(),
true, false, true, false, );
assert_eq!(header.version, 1);
assert_eq!(header.scheme, "https");
assert!(header.sub_present);
assert!(!header.params_present);
assert!(header.frag_present);
assert!(!header.port_present);
}
#[test]
fn test_scheme_codes() {
let https_header = SxurlHeader::new("https".to_string(), false, false, false, false);
let http_header = SxurlHeader::new("http".to_string(), false, false, false, false);
let ftp_header = SxurlHeader::new("ftp".to_string(), false, false, false, false);
assert_eq!(https_header.scheme_code(), 0);
assert_eq!(http_header.scheme_code(), 1);
assert_eq!(ftp_header.scheme_code(), 2);
}
#[test]
fn test_scheme_from_code() {
assert_eq!(SxurlHeader::scheme_from_code(0), Some("https".to_string()));
assert_eq!(SxurlHeader::scheme_from_code(1), Some("http".to_string()));
assert_eq!(SxurlHeader::scheme_from_code(2), Some("ftp".to_string()));
assert_eq!(SxurlHeader::scheme_from_code(3), None);
}
#[test]
fn test_url_components() {
let components = UrlComponents::new(
"https".to_string(),
"com".to_string(),
"example".to_string(),
"api".to_string(),
8443,
"/search".to_string(),
"q=test".to_string(),
"results".to_string(),
);
assert!(components.has_subdomain());
assert!(components.has_params());
assert!(components.has_fragment());
assert!(components.has_port());
}
#[test]
fn test_url_components_empty() {
let components = UrlComponents::new(
"https".to_string(),
"com".to_string(),
"example".to_string(),
"".to_string(),
0,
"/".to_string(),
"".to_string(),
"".to_string(),
);
assert!(!components.has_subdomain());
assert!(!components.has_params());
assert!(!components.has_fragment());
assert!(!components.has_port());
}
}