Skip to content

Commit ae80485

Browse files
committed
Initial work at making url no_std compatible
1 parent 292f3be commit ae80485

File tree

8 files changed

+77
-36
lines changed

8 files changed

+77
-36
lines changed

url/Cargo.toml

+7-3
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,20 @@ edition = "2018"
1919
travis-ci = { repository = "servo/rust-url" }
2020
appveyor = { repository = "Manishearth/rust-url" }
2121

22+
[features]
23+
default = ["std"]
24+
std = ["idna/std"]
25+
2226
[dev-dependencies]
2327
serde_json = "1.0"
2428
bencher = "0.1"
2529

2630
[dependencies]
2731
form_urlencoded = { version = "1.0.0", path = "../form_urlencoded" }
28-
idna = { version = "0.2.0", path = "../idna" }
29-
matches = "0.1"
32+
idna = { version = "0.2.0", default-features = false, path = "../idna" }
33+
matches = "0.1.9"
3034
percent-encoding = { version = "2.1.0", path = "../percent_encoding" }
31-
serde = {version = "1.0", optional = true, features = ["derive"]}
35+
serde = { version = "1.0", default-features = false, optional = true, features = ["derive"] }
3236

3337
[[bench]]
3438
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
@@ -121,6 +121,10 @@ url = { version = "2", features = ["serde"] }
121121
*/
122122

123123
#![doc(html_root_url = "https://docs.rs/url/2.2.2")]
124+
#![no_std]
125+
#[macro_use]
126+
extern crate alloc;
127+
extern crate std;
124128

125129
#[macro_use]
126130
extern crate matches;
@@ -130,20 +134,25 @@ pub use form_urlencoded;
130134
extern crate serde;
131135

132136
use crate::host::HostInternal;
133-
use crate::parser::{to_u32, Context, Parser, SchemeType, PATH_SEGMENT, USERINFO};
134-
use percent_encoding::{percent_decode, percent_encode, utf8_percent_encode};
135-
use std::borrow::Borrow;
136-
use std::cmp;
137-
use std::fmt::{self, Write};
138-
use std::hash;
139-
use std::io;
140-
use std::mem;
141-
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
142-
use std::ops::{Range, RangeFrom, RangeTo};
143-
use std::path::{Path, PathBuf};
144-
use std::str;
145-
146-
use std::convert::TryFrom;
137+
use crate::parser::{to_u32, Context, Parser, SchemeType, USERINFO};
138+
use alloc::borrow::ToOwned;
139+
use alloc::string::{String, ToString};
140+
use core::borrow::Borrow;
141+
use core::cmp;
142+
use core::convert::TryFrom;
143+
use core::fmt::{self, Write};
144+
use core::hash;
145+
use core::mem;
146+
use core::ops::{Range, RangeFrom, RangeTo};
147+
use core::str;
148+
use percent_encoding::utf8_percent_encode;
149+
use std::net::IpAddr;
150+
#[cfg(feature = "std")]
151+
use std::{
152+
io,
153+
net::{SocketAddr, ToSocketAddrs},
154+
path::{Path, PathBuf},
155+
};
147156

148157
pub use crate::host::Host;
149158
pub use crate::origin::{OpaqueOrigin, Origin};
@@ -1136,10 +1145,11 @@ impl Url {
11361145
/// })
11371146
/// }
11381147
/// ```
1148+
#[cfg(feature = "std")]
11391149
pub fn socket_addrs(
11401150
&self,
11411151
default_port_number: impl Fn() -> Option<u16>,
1142-
) -> io::Result<Vec<SocketAddr>> {
1152+
) -> io::Result<alloc::vec::Vec<SocketAddr>> {
11431153
// Note: trying to avoid the Vec allocation by returning `impl AsRef<[SocketAddr]>`
11441154
// causes borrowck issues because the return value borrows `default_port_number`:
11451155
//
@@ -1148,6 +1158,7 @@ impl Url {
11481158
// > This RFC proposes that *all* type parameters are considered in scope
11491159
// > for `impl Trait` in return position
11501160

1161+
// TODO: Return custom error type to support no_std
11511162
fn io_result<T>(opt: Option<T>, message: &str) -> io::Result<T> {
11521163
opt.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, message))
11531164
}
@@ -2298,7 +2309,9 @@ impl Url {
22982309
/// # run().unwrap();
22992310
/// # }
23002311
/// ```
2301-
#[cfg(any(unix, windows, target_os = "redox"))]
2312+
///
2313+
/// This method is only available if the `std` Cargo feature is enabled.
2314+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox")))]
23022315
#[allow(clippy::result_unit_err)]
23032316
pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
23042317
let mut serialization = "file://".to_owned();
@@ -2335,7 +2348,9 @@ impl Url {
23352348
///
23362349
/// Note that `std::path` does not consider trailing slashes significant
23372350
/// and usually does not include them (e.g. in `Path::parent()`).
2338-
#[cfg(any(unix, windows, target_os = "redox"))]
2351+
///
2352+
/// This method is only available if the `std` Cargo feature is enabled.
2353+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox")))]
23392354
#[allow(clippy::result_unit_err)]
23402355
pub fn from_directory_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
23412356
let mut url = Url::from_file_path(path)?;
@@ -2451,8 +2466,10 @@ impl Url {
24512466
/// or if `Path::new_opt()` returns `None`.
24522467
/// (That is, if the percent-decoded path contains a NUL byte or,
24532468
/// for a Windows path, is not UTF-8.)
2469+
///
2470+
/// This method is only available if the `std` Cargo feature is enabled.
24542471
#[inline]
2455-
#[cfg(any(unix, windows, target_os = "redox"))]
2472+
#[cfg(all(feature = "std", any(unix, windows, target_os = "redox")))]
24562473
#[allow(clippy::result_unit_err)]
24572474
pub fn to_file_path(&self) -> Result<PathBuf, ()> {
24582475
if let Some(segments) = self.path_segments() {
@@ -2656,11 +2673,13 @@ impl<'de> serde::Deserialize<'de> for Url {
26562673
}
26572674
}
26582675

2659-
#[cfg(any(unix, target_os = "redox"))]
2676+
#[cfg(all(feature = "std", any(unix, target_os = "redox")))]
26602677
fn path_to_file_url_segments(
26612678
path: &Path,
26622679
serialization: &mut String,
26632680
) -> Result<(u32, HostInternal), ()> {
2681+
use crate::parser::PATH_SEGMENT;
2682+
use percent_encoding::percent_encode;
26642683
use std::os::unix::prelude::OsStrExt;
26652684
if !path.is_absolute() {
26662685
return Err(());
@@ -2683,20 +2702,23 @@ fn path_to_file_url_segments(
26832702
Ok((host_end, HostInternal::None))
26842703
}
26852704

2686-
#[cfg(windows)]
2705+
#[cfg(all(feature = "std", windows))]
26872706
fn path_to_file_url_segments(
26882707
path: &Path,
26892708
serialization: &mut String,
26902709
) -> Result<(u32, HostInternal), ()> {
26912710
path_to_file_url_segments_windows(path, serialization)
26922711
}
26932712

2713+
#[cfg(feature = "std")]
26942714
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
26952715
#[cfg_attr(not(windows), allow(dead_code))]
26962716
fn path_to_file_url_segments_windows(
26972717
path: &Path,
26982718
serialization: &mut String,
26992719
) -> Result<(u32, HostInternal), ()> {
2720+
use crate::parser::PATH_SEGMENT;
2721+
use percent_encoding::percent_encode;
27002722
use std::path::{Component, Prefix};
27012723
if !path.is_absolute() {
27022724
return Err(());
@@ -2751,11 +2773,13 @@ fn path_to_file_url_segments_windows(
27512773
Ok((host_end, host_internal))
27522774
}
27532775

2754-
#[cfg(any(unix, target_os = "redox"))]
2776+
#[cfg(all(feature = "std", any(unix, target_os = "redox")))]
27552777
fn file_url_segments_to_pathbuf(
27562778
host: Option<&str>,
27572779
segments: str::Split<'_, char>,
27582780
) -> Result<PathBuf, ()> {
2781+
use alloc::vec::Vec;
2782+
use percent_encoding::percent_decode;
27592783
use std::ffi::OsStr;
27602784
use std::os::unix::prelude::OsStrExt;
27612785

@@ -2788,20 +2812,22 @@ fn file_url_segments_to_pathbuf(
27882812
Ok(path)
27892813
}
27902814

2791-
#[cfg(windows)]
2815+
#[cfg(all(feature = "std", windows))]
27922816
fn file_url_segments_to_pathbuf(
27932817
host: Option<&str>,
27942818
segments: str::Split<char>,
27952819
) -> Result<PathBuf, ()> {
27962820
file_url_segments_to_pathbuf_windows(host, segments)
27972821
}
27982822

2823+
#[cfg(feature = "std")]
27992824
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
28002825
#[cfg_attr(not(windows), allow(dead_code))]
28012826
fn file_url_segments_to_pathbuf_windows(
28022827
host: Option<&str>,
28032828
mut segments: str::Split<'_, char>,
28042829
) -> Result<PathBuf, ()> {
2830+
use percent_encoding::percent_decode;
28052831
let mut string = if let Some(host) = host {
28062832
r"\\".to_owned() + host
28072833
} else {

url/src/origin.rs

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

1517
pub fn url_origin(url: &Url) -> Origin {
1618
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;
@@ -78,7 +79,8 @@ macro_rules! simple_enum_error {
7879
}
7980
}
8081

81-
impl Error for ParseError {}
82+
#[cfg(feature = "std")]
83+
impl std::error::Error for ParseError {}
8284

8385
simple_enum_error! {
8486
EmptyHost => "empty host",
@@ -1118,7 +1120,7 @@ impl<'a> Parser<'a> {
11181120
while let (Some(c), remaining) = input.split_first() {
11191121
if let Some(digit) = c.to_digit(10) {
11201122
port = port * 10 + digit;
1121-
if port > ::std::u16::MAX as u32 {
1123+
if port > core::u16::MAX as u32 {
11221124
return Err(ParseError::InvalidPort);
11231125
}
11241126
has_any_digit = true;
@@ -1552,7 +1554,7 @@ pub fn ascii_alpha(ch: char) -> bool {
15521554

15531555
#[inline]
15541556
pub fn to_u32(i: usize) -> ParseResult<u32> {
1555-
if i <= ::std::u32::MAX as usize {
1557+
if i <= core::u32::MAX as usize {
15561558
Ok(i as u32)
15571559
} else {
15581560
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)