Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(url): Add quirks::internal_components #788

Merged
merged 4 commits into from Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
1 change: 1 addition & 0 deletions url/Cargo.toml
Expand Up @@ -38,6 +38,7 @@ default = ["idna"]
# UNSTABLE FEATURES (requires Rust nightly)
# Enable to use the #[debugger_visualizer] attribute.
debugger_visualizer = []
expose_internals = []
littledivy marked this conversation as resolved.
Show resolved Hide resolved

[[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 @@ -723,6 +723,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