Skip to content

Commit

Permalink
Initial work at making url no_std compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Feb 17, 2022
1 parent 97221bd commit a4457e0
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 36 deletions.
7 changes: 4 additions & 3 deletions url/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ bencher = "0.1"

[dependencies]
form_urlencoded = { version = "1.0.0", path = "../form_urlencoded" }
idna = { version = "0.2.0", path = "../idna", optional = true }
idna = { version = "0.2.0", default-features = false, path = "../idna", optional = true }
percent-encoding = { version = "2.1.0", path = "../percent_encoding" }
serde = {version = "1.0", optional = true, features = ["derive"]}
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }

[features]
default = ["idna"]
default = ["std", "idna"]
std = ["idna/std"]

[[bench]]
name = "parse_url"
Expand Down
7 changes: 5 additions & 2 deletions url/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp;
use std::fmt::{self, Formatter};
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::cmp;
use core::fmt::{self, Formatter};
use std::net::{Ipv4Addr, Ipv6Addr};

use percent_encoding::{percent_decode, utf8_percent_encode, CONTROLS};
Expand Down
70 changes: 48 additions & 22 deletions url/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,27 +131,36 @@ url = { version = "2", default-features = false }
*/

#![doc(html_root_url = "https://docs.rs/url/2.2.2")]
#![no_std]
#[macro_use]
extern crate alloc;
extern crate std;

pub use form_urlencoded;

#[cfg(feature = "serde")]
extern crate serde;

use crate::host::HostInternal;
use crate::parser::{to_u32, Context, Parser, SchemeType, PATH_SEGMENT, USERINFO};
use percent_encoding::{percent_decode, percent_encode, utf8_percent_encode};
use std::borrow::Borrow;
use std::cmp;
use std::fmt::{self, Write};
use std::hash;
use std::io;
use std::mem;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::ops::{Range, RangeFrom, RangeTo};
use std::path::{Path, PathBuf};
use std::str;

use std::convert::TryFrom;
use crate::parser::{to_u32, Context, Parser, SchemeType, USERINFO};
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use core::borrow::Borrow;
use core::cmp;
use core::convert::TryFrom;
use core::fmt::{self, Write};
use core::hash;
use core::mem;
use core::ops::{Range, RangeFrom, RangeTo};
use core::str;
use percent_encoding::utf8_percent_encode;
use std::net::IpAddr;
#[cfg(feature = "std")]
use std::{
io,
net::{SocketAddr, ToSocketAddrs},
path::{Path, PathBuf},
};

pub use crate::host::Host;
pub use crate::origin::{OpaqueOrigin, Origin};
Expand Down Expand Up @@ -1144,10 +1153,11 @@ impl Url {
/// })
/// }
/// ```
#[cfg(feature = "std")]
pub fn socket_addrs(
&self,
default_port_number: impl Fn() -> Option<u16>,
) -> io::Result<Vec<SocketAddr>> {
) -> io::Result<alloc::vec::Vec<SocketAddr>> {
// Note: trying to avoid the Vec allocation by returning `impl AsRef<[SocketAddr]>`
// causes borrowck issues because the return value borrows `default_port_number`:
//
Expand All @@ -1156,6 +1166,7 @@ impl Url {
// > This RFC proposes that *all* type parameters are considered in scope
// > for `impl Trait` in return position

// TODO: Return custom error type to support no_std
fn io_result<T>(opt: Option<T>, message: &str) -> io::Result<T> {
opt.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, message))
}
Expand Down Expand Up @@ -2314,7 +2325,9 @@ impl Url {
/// # run().unwrap();
/// # }
/// ```
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
///
/// This method is only available if the `std` Cargo feature is enabled.
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
#[allow(clippy::result_unit_err)]
pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut serialization = "file://".to_owned();
Expand Down Expand Up @@ -2351,7 +2364,9 @@ impl Url {
///
/// Note that `std::path` does not consider trailing slashes significant
/// and usually does not include them (e.g. in `Path::parent()`).
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
///
/// This method is only available if the `std` Cargo feature is enabled.
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
#[allow(clippy::result_unit_err)]
pub fn from_directory_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut url = Url::from_file_path(path)?;
Expand Down Expand Up @@ -2467,8 +2482,10 @@ impl Url {
/// or if `Path::new_opt()` returns `None`.
/// (That is, if the percent-decoded path contains a NUL byte or,
/// for a Windows path, is not UTF-8.)
///
/// This method is only available if the `std` Cargo feature is enabled.
#[inline]
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
#[allow(clippy::result_unit_err)]
pub fn to_file_path(&self) -> Result<PathBuf, ()> {
if let Some(segments) = self.path_segments() {
Expand Down Expand Up @@ -2672,11 +2689,13 @@ impl<'de> serde::Deserialize<'de> for Url {
}
}

#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
#[cfg(all(feature = "std", any(unix, target_os = "redox", target_os = "wasi")))]
fn path_to_file_url_segments(
path: &Path,
serialization: &mut String,
) -> Result<(u32, HostInternal), ()> {
use crate::parser::PATH_SEGMENT;
use percent_encoding::percent_encode;
#[cfg(any(unix, target_os = "redox"))]
use std::os::unix::prelude::OsStrExt;
#[cfg(target_os = "wasi")]
Expand All @@ -2702,20 +2721,23 @@ fn path_to_file_url_segments(
Ok((host_end, HostInternal::None))
}

#[cfg(windows)]
#[cfg(all(feature = "std", windows))]
fn path_to_file_url_segments(
path: &Path,
serialization: &mut String,
) -> Result<(u32, HostInternal), ()> {
path_to_file_url_segments_windows(path, serialization)
}

#[cfg(feature = "std")]
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
#[cfg_attr(not(windows), allow(dead_code))]
fn path_to_file_url_segments_windows(
path: &Path,
serialization: &mut String,
) -> Result<(u32, HostInternal), ()> {
use crate::parser::PATH_SEGMENT;
use percent_encoding::percent_encode;
use std::path::{Component, Prefix};
if !path.is_absolute() {
return Err(());
Expand Down Expand Up @@ -2770,11 +2792,13 @@ fn path_to_file_url_segments_windows(
Ok((host_end, host_internal))
}

#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
#[cfg(all(feature = "std", any(unix, target_os = "redox", target_os = "wasi")))]
fn file_url_segments_to_pathbuf(
host: Option<&str>,
segments: str::Split<'_, char>,
) -> Result<PathBuf, ()> {
use alloc::vec::Vec;
use percent_encoding::percent_decode;
use std::ffi::OsStr;
#[cfg(any(unix, target_os = "redox"))]
use std::os::unix::prelude::OsStrExt;
Expand Down Expand Up @@ -2810,20 +2834,22 @@ fn file_url_segments_to_pathbuf(
Ok(path)
}

#[cfg(windows)]
#[cfg(all(feature = "std", windows))]
fn file_url_segments_to_pathbuf(
host: Option<&str>,
segments: str::Split<char>,
) -> Result<PathBuf, ()> {
file_url_segments_to_pathbuf_windows(host, segments)
}

#[cfg(feature = "std")]
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
#[cfg_attr(not(windows), allow(dead_code))]
fn file_url_segments_to_pathbuf_windows(
host: Option<&str>,
mut segments: str::Split<'_, char>,
) -> Result<PathBuf, ()> {
use percent_encoding::percent_decode;
let mut string = if let Some(host) = host {
r"\\".to_owned() + host
} else {
Expand Down
5 changes: 4 additions & 1 deletion url/src/origin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
use crate::host::Host;
use crate::parser::default_port;
use crate::Url;
use std::sync::atomic::{AtomicUsize, Ordering};
use alloc::borrow::ToOwned;
use alloc::string::String;
use core::sync::atomic::{AtomicUsize, Ordering};
use idna::domain_to_unicode;

pub fn url_origin(url: &Url) -> Origin {
let scheme = url.scheme();
Expand Down
14 changes: 8 additions & 6 deletions url/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::error::Error;
use std::fmt::{self, Formatter, Write};
use std::str;
use alloc::borrow::ToOwned;
use alloc::string::{String, ToString};
use core::fmt::{self, Formatter, Write};
use core::str;

use crate::host::{Host, HostInternal};
use crate::Url;
Expand Down Expand Up @@ -72,7 +73,8 @@ macro_rules! simple_enum_error {
}
}

impl Error for ParseError {}
#[cfg(feature = "std")]
impl std::error::Error for ParseError {}

simple_enum_error! {
EmptyHost => "empty host",
Expand Down Expand Up @@ -1107,7 +1109,7 @@ impl<'a> Parser<'a> {
while let (Some(c), remaining) = input.split_first() {
if let Some(digit) = c.to_digit(10) {
port = port * 10 + digit;
if port > ::std::u16::MAX as u32 {
if port > core::u16::MAX as u32 {
return Err(ParseError::InvalidPort);
}
has_any_digit = true;
Expand Down Expand Up @@ -1541,7 +1543,7 @@ pub fn ascii_alpha(ch: char) -> bool {

#[inline]
pub fn to_u32(i: usize) -> ParseResult<u32> {
if i <= ::std::u32::MAX as usize {
if i <= core::u32::MAX as usize {
Ok(i as u32)
} else {
Err(ParseError::Overflow)
Expand Down
3 changes: 2 additions & 1 deletion url/src/path_segments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

use crate::parser::{self, to_u32, SchemeType};
use crate::Url;
use std::str;
use alloc::string::String;
use core::str;

/// Exposes methods to manipulate the path of an URL that is not cannot-be-base.
///
Expand Down
2 changes: 2 additions & 0 deletions url/src/quirks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//! Unless you need to be interoperable with web browsers,
//! you probably want to use `Url` method instead.
use alloc::string::{String, ToString};

use crate::parser::{default_port, Context, Input, Parser, SchemeType};
use crate::{Host, ParseError, Position, Url};

Expand Down
3 changes: 2 additions & 1 deletion url/src/slicing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};

use crate::Url;
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};

impl Index<RangeFull> for Url {
type Output = str;
Expand Down

0 comments on commit a4457e0

Please sign in to comment.