Skip to content

Commit

Permalink
feat(url): add quirks::internal_components (#788)
Browse files Browse the repository at this point in the history
Co-authored-by: Aaron O'Mullan <aaron.omullan@gmail.com>
  • Loading branch information
littledivy and AaronO committed Sep 7, 2022
1 parent 868719d commit a3df365
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Expand Up @@ -49,7 +49,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --features "url/serde"
args: --features "url/serde,url/expose_internals"
# The #[debugger_visualizer] attribute is currently gated behind an unstable feature flag.
# In order to test the visualizers for the url crate, they have to be tested on a nightly build.
- name: Run debugger_visualizer tests
Expand Down
2 changes: 2 additions & 0 deletions url/Cargo.toml
Expand Up @@ -38,6 +38,8 @@ default = ["idna"]
# UNSTABLE FEATURES (requires Rust nightly)
# Enable to use the #[debugger_visualizer] attribute.
debugger_visualizer = []
# Expose internal offsets of the URL.
expose_internals = []

[[bench]]
name = "parse_url"
Expand Down
43 changes: 43 additions & 0 deletions url/src/quirks.rs
Expand Up @@ -14,6 +14,49 @@
use crate::parser::{default_port, Context, Input, Parser, SchemeType};
use crate::{Host, ParseError, Position, Url};

/// Internal components / offsets of a URL.
///
/// https://user@pass:example.com:1234/foo/bar?baz#quux
/// | | | | ^^^^| | |
/// | | | | | | | `----- fragment_start
/// | | | | | | `--------- query_start
/// | | | | | `----------------- path_start
/// | | | | `--------------------- port
/// | | | `----------------------- host_end
/// | | `---------------------------------- host_start
/// | `--------------------------------------- username_end
/// `---------------------------------------------- scheme_end
#[derive(Copy, Clone)]
#[cfg(feature = "expose_internals")]
pub struct InternalComponents {
pub scheme_end: u32,
pub username_end: u32,
pub host_start: u32,
pub host_end: u32,
pub port: Option<u16>,
pub path_start: u32,
pub query_start: Option<u32>,
pub fragment_start: Option<u32>,
}

/// Internal component / parsed offsets of the URL.
///
/// This can be useful for implementing efficient serialization
/// for the URL.
#[cfg(feature = "expose_internals")]
pub fn internal_components(url: &Url) -> InternalComponents {
InternalComponents {
scheme_end: url.scheme_end,
username_end: url.username_end,
host_start: url.host_start,
host_end: url.host_end,
port: url.port,
path_start: url.path_start,
query_start: url.query_start,
fragment_start: url.fragment_start,
}
}

/// https://url.spec.whatwg.org/#dom-url-domaintoascii
pub fn domain_to_ascii(domain: &str) -> String {
match Host::parse(domain) {
Expand Down
28 changes: 28 additions & 0 deletions url/tests/unit.rs
Expand Up @@ -731,6 +731,34 @@ fn test_domain_encoding_quirks() {
}
}

#[cfg(feature = "expose_internals")]
#[test]
fn test_expose_internals() {
use url::quirks::internal_components;
use url::quirks::InternalComponents;

let url = Url::parse("https://example.com/path/file.ext?key=val&key2=val2#fragment").unwrap();
let InternalComponents {
scheme_end,
username_end,
host_start,
host_end,
port,
path_start,
query_start,
fragment_start,
} = internal_components(&url);

assert_eq!(scheme_end, 5);
assert_eq!(username_end, 8);
assert_eq!(host_start, 8);
assert_eq!(host_end, 19);
assert_eq!(port, None);
assert_eq!(path_start, 19);
assert_eq!(query_start, Some(33));
assert_eq!(fragment_start, Some(51));
}

#[test]
fn test_windows_unc_path() {
if !cfg!(windows) {
Expand Down

0 comments on commit a3df365

Please sign in to comment.