Skip to content

Commit ca287d4

Browse files
committed
Initial work at making url no_std compatible
1 parent 6853f7f commit ca287d4

File tree

8 files changed

+75
-36
lines changed

8 files changed

+75
-36
lines changed

url/Cargo.toml

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ bencher = "0.1"
2626

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

3333
[features]
34-
default = ["idna"]
34+
default = ["std", "idna"]
35+
std = ["idna/std"]
3536

3637
[[bench]]
3738
name = "parse_url"

url/src/host.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use std::cmp;
10-
use std::fmt::{self, Formatter};
9+
use alloc::borrow::ToOwned;
10+
use alloc::string::{String, ToString};
11+
use alloc::vec::Vec;
12+
use core::cmp;
13+
use core::fmt::{self, Formatter};
1114
use std::net::{Ipv4Addr, Ipv6Addr};
1215

1316
use percent_encoding::{percent_decode, utf8_percent_encode, CONTROLS};

url/src/lib.rs

+48-22
Original file line numberDiff line numberDiff line change
@@ -131,27 +131,36 @@ url = { version = "2", default-features = false }
131131
*/
132132

133133
#![doc(html_root_url = "https://docs.rs/url/2.2.2")]
134+
#![no_std]
135+
#[macro_use]
136+
extern crate alloc;
137+
extern crate std;
134138

135139
pub use form_urlencoded;
136140

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

140144
use crate::host::HostInternal;
141-
use crate::parser::{to_u32, Context, Parser, SchemeType, PATH_SEGMENT, USERINFO};
142-
use percent_encoding::{percent_decode, percent_encode, utf8_percent_encode};
143-
use std::borrow::Borrow;
144-
use std::cmp;
145-
use std::fmt::{self, Write};
146-
use std::hash;
147-
use std::io;
148-
use std::mem;
149-
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
150-
use std::ops::{Range, RangeFrom, RangeTo};
151-
use std::path::{Path, PathBuf};
152-
use std::str;
153-
154-
use std::convert::TryFrom;
145+
use crate::parser::{to_u32, Context, Parser, SchemeType, USERINFO};
146+
use alloc::borrow::ToOwned;
147+
use alloc::string::{String, ToString};
148+
use core::borrow::Borrow;
149+
use core::cmp;
150+
use core::convert::TryFrom;
151+
use core::fmt::{self, Write};
152+
use core::hash;
153+
use core::mem;
154+
use core::ops::{Range, RangeFrom, RangeTo};
155+
use core::str;
156+
use percent_encoding::utf8_percent_encode;
157+
use std::net::IpAddr;
158+
#[cfg(feature = "std")]
159+
use std::{
160+
io,
161+
net::{SocketAddr, ToSocketAddrs},
162+
path::{Path, PathBuf},
163+
};
155164

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

1169+
// TODO: Return custom error type to support no_std
11591170
fn io_result<T>(opt: Option<T>, message: &str) -> io::Result<T> {
11601171
opt.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, message))
11611172
}
@@ -2314,7 +2325,9 @@ impl Url {
23142325
/// # run().unwrap();
23152326
/// # }
23162327
/// ```
2317-
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
2328+
///
2329+
/// This method is only available if the `std` Cargo feature is enabled.
2330+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
23182331
#[allow(clippy::result_unit_err)]
23192332
pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
23202333
let mut serialization = "file://".to_owned();
@@ -2351,7 +2364,9 @@ impl Url {
23512364
///
23522365
/// Note that `std::path` does not consider trailing slashes significant
23532366
/// and usually does not include them (e.g. in `Path::parent()`).
2354-
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
2367+
///
2368+
/// This method is only available if the `std` Cargo feature is enabled.
2369+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
23552370
#[allow(clippy::result_unit_err)]
23562371
pub fn from_directory_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
23572372
let mut url = Url::from_file_path(path)?;
@@ -2467,8 +2482,10 @@ impl Url {
24672482
/// or if `Path::new_opt()` returns `None`.
24682483
/// (That is, if the percent-decoded path contains a NUL byte or,
24692484
/// for a Windows path, is not UTF-8.)
2485+
///
2486+
/// This method is only available if the `std` Cargo feature is enabled.
24702487
#[inline]
2471-
#[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
2488+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox", target_os = "wasi")))]
24722489
#[allow(clippy::result_unit_err)]
24732490
pub fn to_file_path(&self) -> Result<PathBuf, ()> {
24742491
if let Some(segments) = self.path_segments() {
@@ -2672,11 +2689,13 @@ impl<'de> serde::Deserialize<'de> for Url {
26722689
}
26732690
}
26742691

2675-
#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
2692+
#[cfg(all(feature = "std", any(unix, target_os = "redox", target_os = "wasi")))]
26762693
fn path_to_file_url_segments(
26772694
path: &Path,
26782695
serialization: &mut String,
26792696
) -> Result<(u32, HostInternal), ()> {
2697+
use crate::parser::PATH_SEGMENT;
2698+
use percent_encoding::percent_encode;
26802699
#[cfg(any(unix, target_os = "redox"))]
26812700
use std::os::unix::prelude::OsStrExt;
26822701
#[cfg(target_os = "wasi")]
@@ -2702,20 +2721,23 @@ fn path_to_file_url_segments(
27022721
Ok((host_end, HostInternal::None))
27032722
}
27042723

2705-
#[cfg(windows)]
2724+
#[cfg(all(feature = "std", windows))]
27062725
fn path_to_file_url_segments(
27072726
path: &Path,
27082727
serialization: &mut String,
27092728
) -> Result<(u32, HostInternal), ()> {
27102729
path_to_file_url_segments_windows(path, serialization)
27112730
}
27122731

2732+
#[cfg(feature = "std")]
27132733
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
27142734
#[cfg_attr(not(windows), allow(dead_code))]
27152735
fn path_to_file_url_segments_windows(
27162736
path: &Path,
27172737
serialization: &mut String,
27182738
) -> Result<(u32, HostInternal), ()> {
2739+
use crate::parser::PATH_SEGMENT;
2740+
use percent_encoding::percent_encode;
27192741
use std::path::{Component, Prefix};
27202742
if !path.is_absolute() {
27212743
return Err(());
@@ -2770,11 +2792,13 @@ fn path_to_file_url_segments_windows(
27702792
Ok((host_end, host_internal))
27712793
}
27722794

2773-
#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
2795+
#[cfg(all(feature = "std", any(unix, target_os = "redox", target_os = "wasi")))]
27742796
fn file_url_segments_to_pathbuf(
27752797
host: Option<&str>,
27762798
segments: str::Split<'_, char>,
27772799
) -> Result<PathBuf, ()> {
2800+
use alloc::vec::Vec;
2801+
use percent_encoding::percent_decode;
27782802
use std::ffi::OsStr;
27792803
#[cfg(any(unix, target_os = "redox"))]
27802804
use std::os::unix::prelude::OsStrExt;
@@ -2810,20 +2834,22 @@ fn file_url_segments_to_pathbuf(
28102834
Ok(path)
28112835
}
28122836

2813-
#[cfg(windows)]
2837+
#[cfg(all(feature = "std", windows))]
28142838
fn file_url_segments_to_pathbuf(
28152839
host: Option<&str>,
28162840
segments: str::Split<char>,
28172841
) -> Result<PathBuf, ()> {
28182842
file_url_segments_to_pathbuf_windows(host, segments)
28192843
}
28202844

2845+
#[cfg(feature = "std")]
28212846
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
28222847
#[cfg_attr(not(windows), allow(dead_code))]
28232848
fn file_url_segments_to_pathbuf_windows(
28242849
host: Option<&str>,
28252850
mut segments: str::Split<'_, char>,
28262851
) -> Result<PathBuf, ()> {
2852+
use percent_encoding::percent_decode;
28272853
let mut string = if let Some(host) = host {
28282854
r"\\".to_owned() + host
28292855
} else {

url/src/origin.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
use crate::host::Host;
1010
use crate::parser::default_port;
1111
use crate::Url;
12-
use std::sync::atomic::{AtomicUsize, Ordering};
12+
use alloc::borrow::ToOwned;
13+
use alloc::string::String;
14+
use core::sync::atomic::{AtomicUsize, Ordering};
15+
use idna::domain_to_unicode;
1316

1417
pub fn url_origin(url: &Url) -> Origin {
1518
let scheme = url.scheme();

url/src/parser.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use std::error::Error;
10-
use std::fmt::{self, Formatter, Write};
11-
use std::str;
9+
use alloc::borrow::ToOwned;
10+
use alloc::string::{String, ToString};
11+
use core::fmt::{self, Formatter, Write};
12+
use core::str;
1213

1314
use crate::host::{Host, HostInternal};
1415
use crate::Url;
@@ -72,7 +73,8 @@ macro_rules! simple_enum_error {
7273
}
7374
}
7475

75-
impl Error for ParseError {}
76+
#[cfg(feature = "std")]
77+
impl std::error::Error for ParseError {}
7678

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

15421544
#[inline]
15431545
pub fn to_u32(i: usize) -> ParseResult<u32> {
1544-
if i <= ::std::u32::MAX as usize {
1546+
if i <= core::u32::MAX as usize {
15451547
Ok(i as u32)
15461548
} else {
15471549
Err(ParseError::Overflow)

url/src/path_segments.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
use crate::parser::{self, to_u32, SchemeType};
1010
use crate::Url;
11-
use std::str;
11+
use alloc::string::String;
12+
use core::str;
1213

1314
/// Exposes methods to manipulate the path of an URL that is not cannot-be-base.
1415
///

url/src/quirks.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
//! Unless you need to be interoperable with web browsers,
1212
//! you probably want to use `Url` method instead.
1313
14+
use alloc::string::{String, ToString};
15+
1416
use crate::parser::{default_port, Context, Input, Parser, SchemeType};
1517
use crate::{Host, ParseError, Position, Url};
1618

url/src/slicing.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9+
use core::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
10+
911
use crate::Url;
10-
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
1112

1213
impl Index<RangeFull> for Url {
1314
type Output = str;

0 commit comments

Comments
 (0)