Bug 1953750 - Move mozurl to Rust 2021. r=necko-reviewers,valentin
Bump `mozurl` to Rust edition 2021 Differential Revision: https://phabricator.services.mozilla.com/D241372
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
edition = "2015"
|
||||
edition = "2021"
|
||||
name = "mozurl"
|
||||
version = "0.0.1"
|
||||
authors = ["Nika Layzell <nika@thelayzells.com>"]
|
||||
@@ -11,3 +11,75 @@ nserror = { path = "../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../xpcom/rust/nsstring" }
|
||||
xpcom = { path = "../../../xpcom/rust/xpcom" }
|
||||
uuid = { version = "1.0", features = ["v4"] }
|
||||
|
||||
# Keep in sync with neqo
|
||||
[lints.rust]
|
||||
absolute_paths_not_starting_with_crate = "warn"
|
||||
ambiguous_negative_literals = "warn"
|
||||
explicit_outlives_requirements = "warn"
|
||||
macro_use_extern_crate = "warn"
|
||||
missing_abi = "warn"
|
||||
non_ascii_idents = "warn"
|
||||
redundant_imports = "warn"
|
||||
redundant_lifetimes = "warn"
|
||||
trivial_numeric_casts = "warn"
|
||||
unit_bindings = "warn"
|
||||
unused_import_braces = "warn"
|
||||
unused_lifetimes = "warn"
|
||||
unused_macro_rules = "warn"
|
||||
unused_qualifications = "warn"
|
||||
|
||||
# Keep in sync with neqo
|
||||
[lints.clippy]
|
||||
cargo = { level = "warn", priority = -1 }
|
||||
nursery = { level = "warn", priority = -1 }
|
||||
pedantic = { level = "warn", priority = -1 }
|
||||
allow_attributes = "warn"
|
||||
allow_attributes_without_reason = "warn"
|
||||
cfg_not_test = "warn"
|
||||
clone_on_ref_ptr = "warn"
|
||||
create_dir = "warn"
|
||||
dbg_macro = "warn"
|
||||
empty_drop = "warn"
|
||||
empty_enum_variants_with_brackets = "warn"
|
||||
filetype_is_file = "warn"
|
||||
float_cmp_const = "warn"
|
||||
fn_to_numeric_cast_any = "warn"
|
||||
get_unwrap = "warn"
|
||||
if_then_some_else_none = "warn"
|
||||
infinite_loop = "warn"
|
||||
large_include_file = "warn"
|
||||
let_underscore_must_use = "warn"
|
||||
let_underscore_untyped = "warn"
|
||||
literal_string_with_formatting_args = "allow" # FIXME: Re-enable "warn" when MSRV is > 1.87. See https://github.com/rust-lang/rust-clippy/pull/13953#issuecomment-2676336899
|
||||
lossy_float_literal = "warn"
|
||||
mem_forget = "warn"
|
||||
mixed_read_write_in_expression = "warn"
|
||||
multiple_crate_versions = "allow"
|
||||
multiple_inherent_impl = "warn"
|
||||
mutex_atomic = "warn"
|
||||
mutex_integer = "warn"
|
||||
needless_raw_strings = "warn"
|
||||
pathbuf_init_then_push = "warn"
|
||||
pub_without_shorthand = "warn"
|
||||
rc_buffer = "warn"
|
||||
rc_mutex = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
ref_patterns = "warn"
|
||||
renamed_function_params = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
self_named_module_files = "warn"
|
||||
semicolon_inside_block = "warn"
|
||||
string_lit_chars_any = "warn"
|
||||
string_to_string = "warn"
|
||||
suspicious_xor_used_as_pow = "warn"
|
||||
try_err = "warn"
|
||||
unnecessary_safety_comment = "warn"
|
||||
unnecessary_safety_doc = "warn"
|
||||
unnecessary_self_imports = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unused_result_ok = "warn"
|
||||
unused_trait_names = "warn"
|
||||
unwrap_in_result = "warn"
|
||||
unwrap_used = "warn"
|
||||
verbose_file_reads = "warn"
|
||||
|
||||
@@ -3,35 +3,35 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#![expect(
|
||||
clippy::missing_safety_doc,
|
||||
clippy::missing_panics_doc,
|
||||
reason = "OK here"
|
||||
)]
|
||||
|
||||
extern crate url;
|
||||
use url::quirks;
|
||||
use url::{ParseOptions, Position, Url};
|
||||
use url::{quirks, ParseOptions, Position, Url};
|
||||
|
||||
extern crate nsstring;
|
||||
use nsstring::{nsACString, nsCString};
|
||||
|
||||
extern crate nserror;
|
||||
use nserror::*;
|
||||
use nserror::{nsresult, NS_ERROR_MALFORMED_URI, NS_ERROR_UNEXPECTED, NS_OK};
|
||||
|
||||
extern crate xpcom;
|
||||
use xpcom::{AtomicRefcnt, RefCounted, RefPtr};
|
||||
|
||||
extern crate uuid;
|
||||
use uuid::Uuid;
|
||||
use std::{fmt::Write as _, marker::PhantomData, ops, ptr, str};
|
||||
|
||||
use std::fmt::Write;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use uuid::Uuid;
|
||||
|
||||
extern "C" {
|
||||
fn Gecko_StrictFileOriginPolicy() -> bool;
|
||||
}
|
||||
|
||||
/// Helper macro. If the expression $e is Ok(t) evaluates to t, otherwise,
|
||||
/// returns NS_ERROR_MALFORMED_URI.
|
||||
/// returns `NS_ERROR_MALFORMED_URI`.
|
||||
macro_rules! try_or_malformed {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
@@ -49,21 +49,19 @@ fn default_port(scheme: &str) -> Option<u16> {
|
||||
match scheme {
|
||||
"ftp" => Some(21),
|
||||
"gopher" => Some(70),
|
||||
"http" => Some(80),
|
||||
"https" => Some(443),
|
||||
"ws" => Some(80),
|
||||
"wss" => Some(443),
|
||||
"rtsp" => Some(443),
|
||||
"android" => Some(443),
|
||||
"http" | "ws" => Some(80),
|
||||
"https" | "wss" | "rtsp" | "android" => Some(443),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// A slice into the backing string. This type is only valid as long as the
|
||||
/// MozURL which it was pulled from is valid. In C++, this type implicitly
|
||||
/// converts to a nsDependentCString, and is an implementation detail.
|
||||
/// A slice into the backing string.
|
||||
///
|
||||
/// This type exists because, unlike &str, this type is safe to return over FFI.
|
||||
/// This type is only valid as long as the [`MozURL`] which it was pulled from is
|
||||
/// valid. In C++, this type implicitly converts to a `nsDependentCString`, and is
|
||||
/// an implementation detail.
|
||||
///
|
||||
/// This type exists because, unlike `&str`, this type is safe to return over FFI.
|
||||
#[repr(C)]
|
||||
pub struct SpecSlice<'a> {
|
||||
data: *const u8,
|
||||
@@ -72,17 +70,16 @@ pub struct SpecSlice<'a> {
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for SpecSlice<'a> {
|
||||
fn from(s: &'a str) -> SpecSlice<'a> {
|
||||
assert!(s.len() < u32::max_value() as usize);
|
||||
fn from(s: &'a str) -> Self {
|
||||
SpecSlice {
|
||||
data: s.as_ptr(),
|
||||
len: s.len() as u32,
|
||||
len: u32::try_from(s.len()).expect("string length not representable in u32"),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The MozURL reference-counted threadsafe URL type. This type intentionally
|
||||
/// The [`MozURL`] reference-counted threadsafe URL type. This type intentionally
|
||||
/// implements no XPCOM interfaces, and all method calls are non-virtual.
|
||||
#[repr(C)]
|
||||
pub struct MozURL {
|
||||
@@ -91,15 +88,16 @@ pub struct MozURL {
|
||||
}
|
||||
|
||||
impl MozURL {
|
||||
pub fn from_url(url: Url) -> RefPtr<MozURL> {
|
||||
#[must_use]
|
||||
pub fn from_url(url: Url) -> RefPtr<Self> {
|
||||
// Actually allocate the URL on the heap. This is the only place we actually
|
||||
// create a MozURL, other than in clone().
|
||||
// create a [`MozURL`], other than in `clone()`.
|
||||
unsafe {
|
||||
RefPtr::from_raw(Box::into_raw(Box::new(MozURL {
|
||||
url: url,
|
||||
RefPtr::from_raw(Box::into_raw(Box::new(Self {
|
||||
url,
|
||||
refcnt: AtomicRefcnt::new(),
|
||||
})))
|
||||
.unwrap()
|
||||
.expect("MozURL created OK")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,7 +124,7 @@ pub unsafe extern "C" fn mozurl_addref(url: &MozURL) {
|
||||
pub unsafe extern "C" fn mozurl_release(url: &MozURL) {
|
||||
let rc = url.refcnt.dec();
|
||||
if rc == 0 {
|
||||
mem::drop(Box::from_raw(url as *const MozURL as *mut MozURL));
|
||||
drop(Box::from_raw(ptr::from_ref::<MozURL>(url).cast_mut()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +159,7 @@ pub extern "C" fn mozurl_new(
|
||||
NS_OK
|
||||
}
|
||||
|
||||
/// Allocate a new MozURL object which is a clone of the original, and store a
|
||||
/// Allocate a new [`MozURL`] object which is a clone of the original, and store a
|
||||
/// pointer to it into newurl.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_clone(url: &MozURL, newurl: &mut *const MozURL) {
|
||||
@@ -200,15 +198,14 @@ pub extern "C" fn mozurl_host(url: &MozURL) -> SpecSlice {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_port(url: &MozURL) -> i32 {
|
||||
// NOTE: Gecko uses -1 to represent the default port.
|
||||
url.port().map(|p| p as i32).unwrap_or(-1)
|
||||
url.port().map_or(-1, i32::from)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_real_port(url: &MozURL) -> i32 {
|
||||
url.port()
|
||||
.or_else(|| default_port(url.scheme()))
|
||||
.map(|p| p as i32)
|
||||
.unwrap_or(-1)
|
||||
.map_or(-1, i32::from)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -256,11 +253,10 @@ pub extern "C" fn mozurl_has_query(url: &MozURL) -> bool {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_directory(url: &MozURL) -> SpecSlice {
|
||||
if let Some(position) = url.path().rfind('/') {
|
||||
url.path()[..position + 1].into()
|
||||
} else {
|
||||
url.path().into()
|
||||
}
|
||||
url.path().rfind('/').map_or_else(
|
||||
|| url.path().into(),
|
||||
|position| url.path()[..=position].into(),
|
||||
)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -281,7 +277,12 @@ fn get_origin(url: &MozURL) -> Option<String> {
|
||||
if port == default_port(url.scheme()) {
|
||||
Some(format!("{}://{}", url.scheme(), host))
|
||||
} else {
|
||||
Some(format!("{}://{}:{}", url.scheme(), host, port.unwrap()))
|
||||
Some(format!(
|
||||
"{}://{}:{}",
|
||||
url.scheme(),
|
||||
host,
|
||||
port.expect("got a port")
|
||||
))
|
||||
}
|
||||
}
|
||||
"file" => {
|
||||
@@ -298,10 +299,10 @@ fn get_origin(url: &MozURL) -> Option<String> {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_origin(url: &MozURL, origin: &mut nsACString) {
|
||||
let origin_str = if !url.as_ref().starts_with("about:blank") {
|
||||
get_origin(url)
|
||||
} else {
|
||||
let origin_str = if url.as_ref().starts_with("about:blank") {
|
||||
None
|
||||
} else {
|
||||
get_origin(url)
|
||||
};
|
||||
|
||||
let origin_str = origin_str.unwrap_or_else(|| {
|
||||
@@ -375,7 +376,7 @@ pub extern "C" fn mozurl_set_hostname(url: &mut MozURL, host: &nsACString) -> ns
|
||||
pub extern "C" fn mozurl_set_port_no(url: &mut MozURL, new_port: i32) -> nsresult {
|
||||
debug_assert_mut!(url);
|
||||
|
||||
if new_port > u16::MAX as i32 {
|
||||
if new_port > i32::from(u16::MAX) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@@ -383,8 +384,9 @@ pub extern "C" fn mozurl_set_port_no(url: &mut MozURL, new_port: i32) -> nsresul
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
|
||||
#[expect(clippy::cast_sign_loss, reason = "not possible due to first match arm")]
|
||||
let port = match new_port {
|
||||
new if new < 0 || u16::max_value() as i32 <= new => None,
|
||||
new if new < 0 || i32::from(u16::MAX) <= new => None,
|
||||
new if Some(new as u16) == default_port(url.scheme()) => None,
|
||||
new => Some(new as u16),
|
||||
};
|
||||
@@ -419,7 +421,7 @@ pub extern "C" fn mozurl_set_fragment(url: &mut MozURL, fragment: &nsACString) -
|
||||
#[no_mangle]
|
||||
pub extern "C" fn mozurl_sizeof(url: &MozURL) -> usize {
|
||||
debug_assert_mut!(url);
|
||||
mem::size_of::<MozURL>() + url.as_str().len()
|
||||
size_of::<MozURL>() + url.as_str().len()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -485,7 +487,7 @@ pub extern "C" fn mozurl_relative(
|
||||
match (url1.path_segments(), url2.path_segments()) {
|
||||
(Some(mut path1), Some(mut path2)) => {
|
||||
// Exhaust the part of the iterators that match
|
||||
while let (Some(ref p1), Some(ref p2)) = (path1.next(), path2.next()) {
|
||||
while let (Some(p1), Some(p2)) = (&path1.next(), &path2.next()) {
|
||||
if p1 != p2 {
|
||||
break;
|
||||
}
|
||||
@@ -512,6 +514,6 @@ pub extern "C" fn mozurl_relative(
|
||||
pub extern "C" fn rusturl_parse_ipv6addr(input: &nsACString, addr: &mut nsACString) -> nsresult {
|
||||
let ip6 = try_or_malformed!(str::from_utf8(input));
|
||||
let host = try_or_malformed!(url::Host::parse(ip6));
|
||||
let _ = write!(addr, "{}", host);
|
||||
_ = write!(addr, "{host}");
|
||||
NS_OK
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user