Skip to content

Commit 61297c5

Browse files
committed
feat: add UrlComponents struct
1 parent 7fa139a commit 61297c5

File tree

1 file changed

+71
-43
lines changed

1 file changed

+71
-43
lines changed

src/lib.rs

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,66 @@ impl From<c_uint> for HostType {
6767
}
6868
}
6969

70+
/// By using 32-bit integers, we implicitly assume that the URL string
71+
/// cannot exceed 4 GB.
72+
///
73+
/// https://user:[email protected]:1234/foo/bar?baz#quux
74+
/// | | | | ^^^^| | |
75+
/// | | | | | | | `----- hash_start
76+
/// | | | | | | `--------- search_start
77+
/// | | | | | `----------------- pathname_start
78+
/// | | | | `--------------------- port
79+
/// | | | `----------------------- host_end
80+
/// | | `---------------------------------- host_start
81+
/// | `--------------------------------------- username_end
82+
/// `--------------------------------------------- protocol_end
83+
#[derive(Debug)]
84+
pub struct UrlComponents {
85+
pub protocol_end: u32,
86+
pub username_end: u32,
87+
pub host_start: u32,
88+
pub host_end: u32,
89+
pub port: Option<u32>,
90+
pub pathname_start: Option<u32>,
91+
pub search_start: Option<u32>,
92+
pub hash_start: Option<u32>,
93+
}
94+
95+
impl From<&ffi::ada_url_components> for UrlComponents {
96+
fn from(value: &ffi::ada_url_components) -> Self {
97+
let port = if value.port == u32::MAX {
98+
None
99+
} else {
100+
Some(value.port)
101+
};
102+
let pathname_start = if value.pathname_start == u32::MAX {
103+
None
104+
} else {
105+
Some(value.pathname_start)
106+
};
107+
let search_start = if value.search_start == u32::MAX {
108+
None
109+
} else {
110+
Some(value.search_start)
111+
};
112+
let hash_start = if value.hash_start == u32::MAX {
113+
None
114+
} else {
115+
Some(value.hash_start)
116+
};
117+
Self {
118+
protocol_end: value.protocol_end,
119+
username_end: value.username_end,
120+
host_start: value.host_start,
121+
host_end: value.host_end,
122+
port,
123+
pathname_start,
124+
search_start,
125+
hash_start,
126+
}
127+
}
128+
}
129+
70130
/// A parsed URL struct according to WHATWG URL specification.
71131
#[derive(Eq)]
72132
pub struct Url(*mut ffi::ada_url);
@@ -87,7 +147,7 @@ impl Drop for Url {
87147

88148
impl From<*mut ffi::ada_url> for Url {
89149
fn from(value: *mut ffi::ada_url) -> Self {
90-
Self { 0: value }
150+
Self(value)
91151
}
92152
}
93153

@@ -395,12 +455,18 @@ impl Url {
395455
pub fn has_search(&self) -> bool {
396456
unsafe { ffi::ada_has_search(self.0) }
397457
}
458+
398459
/// Returns the parsed version of the URL with all components.
399460
///
400461
/// For more information, read [WHATWG URL spec](https://url.spec.whatwg.org/#dom-url-href)
401462
pub fn as_str(&self) -> &str {
402463
self.href()
403464
}
465+
466+
/// Returns the URL components of the instance.
467+
pub fn components(&self) -> UrlComponents {
468+
unsafe { ffi::ada_get_components(self.0).as_ref().unwrap() }.into()
469+
}
404470
}
405471

406472
/// Serializes this URL into a `serde` stream.
@@ -508,48 +574,10 @@ impl From<Url> for String {
508574

509575
impl fmt::Debug for Url {
510576
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
511-
unsafe {
512-
let components = ffi::ada_get_components(self.0).as_ref().unwrap();
513-
let mut debug = f.debug_struct("Url");
514-
debug
515-
.field("href", &self.href())
516-
.field("protocol_end", &components.protocol_end)
517-
.field("host_start", &components.host_start)
518-
.field("host_end", &components.host_end);
519-
let port = if components.port == u32::MAX {
520-
None
521-
} else {
522-
Some(components.port)
523-
};
524-
let username_end = if components.username_end == u32::MAX {
525-
None
526-
} else {
527-
Some(components.username_end)
528-
};
529-
let search_start = if components.search_start == u32::MAX {
530-
None
531-
} else {
532-
Some(components.search_start)
533-
};
534-
let hash_start = if components.hash_start == u32::MAX {
535-
None
536-
} else {
537-
Some(components.hash_start)
538-
};
539-
let pathname_start = if components.pathname_start == u32::MAX {
540-
None
541-
} else {
542-
Some(components.pathname_start)
543-
};
544-
545-
debug
546-
.field("port", &port)
547-
.field("username_end", &username_end)
548-
.field("search_start", &search_start)
549-
.field("hash_start", &hash_start)
550-
.field("pathname_start", &pathname_start)
551-
.finish()
552-
}
577+
f.debug_struct("Url")
578+
.field("href", &self.href())
579+
.field("components", &self.components())
580+
.finish()
553581
}
554582
}
555583

0 commit comments

Comments
 (0)