@@ -127,27 +127,44 @@ url = { version = "2", features = ["serde"] }
127127 feature( debugger_visualizer) ,
128128 debugger_visualizer( natvis_file = "../../debug_metadata/url.natvis" )
129129) ]
130+ #![ no_std]
130131
131132pub use form_urlencoded;
132133
134+ // For forwards compatibility
135+ #[ cfg( feature = "std" ) ]
136+ extern crate std;
137+
138+ #[ macro_use]
139+ extern crate alloc;
140+
141+ #[ cfg( not( feature = "alloc" ) ) ]
142+ compile_error ! ( "the `alloc` feature must be enabled" ) ;
143+
133144#[ cfg( feature = "serde" ) ]
134145extern crate serde;
135146
136147use crate :: host:: HostInternal ;
137- use crate :: parser:: { to_u32, Context , Parser , SchemeType , PATH_SEGMENT , USERINFO } ;
138- use percent_encoding:: { percent_decode, percent_encode, utf8_percent_encode} ;
139- use std:: borrow:: Borrow ;
140- use std:: cmp;
141- use std:: fmt:: { self , Write } ;
142- use std:: hash;
143- use std:: io;
144- use std:: mem;
145- use std:: net:: { IpAddr , SocketAddr , ToSocketAddrs } ;
146- use std:: ops:: { Range , RangeFrom , RangeTo } ;
147- use std:: path:: { Path , PathBuf } ;
148- use std:: str;
149-
150- use std:: convert:: TryFrom ;
148+ use crate :: parser:: { to_u32, Context , Parser , SchemeType , USERINFO } ;
149+ use alloc:: borrow:: ToOwned ;
150+ use alloc:: string:: { String , ToString } ;
151+ use core:: borrow:: Borrow ;
152+ use core:: cmp;
153+ use core:: convert:: TryFrom ;
154+ use core:: fmt:: { self , Write } ;
155+ use core:: hash;
156+ use core:: mem;
157+ use core:: ops:: { Range , RangeFrom , RangeTo } ;
158+ use core:: str;
159+ use no_std_net:: IpAddr ;
160+ use percent_encoding:: utf8_percent_encode;
161+
162+ #[ cfg( feature = "std" ) ]
163+ use std:: {
164+ io,
165+ net:: { SocketAddr , ToSocketAddrs } ,
166+ path:: { Path , PathBuf } ,
167+ } ;
151168
152169pub use crate :: host:: Host ;
153170pub use crate :: origin:: { OpaqueOrigin , Origin } ;
@@ -1237,10 +1254,11 @@ impl Url {
12371254 /// })
12381255 /// }
12391256 /// ```
1257+ #[ cfg( feature = "std" ) ]
12401258 pub fn socket_addrs (
12411259 & self ,
12421260 default_port_number : impl Fn ( ) -> Option < u16 > ,
1243- ) -> io:: Result < Vec < SocketAddr > > {
1261+ ) -> io:: Result < alloc :: vec :: Vec < SocketAddr > > {
12441262 // Note: trying to avoid the Vec allocation by returning `impl AsRef<[SocketAddr]>`
12451263 // causes borrowck issues because the return value borrows `default_port_number`:
12461264 //
@@ -1249,6 +1267,7 @@ impl Url {
12491267 // > This RFC proposes that *all* type parameters are considered in scope
12501268 // > for `impl Trait` in return position
12511269
1270+ // TODO: Return custom error type to support no_std
12521271 fn io_result < T > ( opt : Option < T > , message : & str ) -> io:: Result < T > {
12531272 opt. ok_or_else ( || io:: Error :: new ( io:: ErrorKind :: InvalidData , message) )
12541273 }
@@ -1310,9 +1329,23 @@ impl Url {
13101329 ///
13111330 /// ```
13121331 /// use url::Url;
1313- /// # use std::error::Error;
13141332 ///
1315- /// # fn run() -> Result<(), Box<dyn Error>> {
1333+ /// # use url::ParseError;
1334+ /// # #[derive(Debug)]
1335+ /// # /// A simple wrapper error struct for `no_std` support
1336+ /// # struct TestError;
1337+ /// # impl From<ParseError> for TestError {
1338+ /// # fn from(value: ParseError) -> Self {
1339+ /// # TestError {}
1340+ /// # }
1341+ /// # }
1342+ /// # impl From<&str> for TestError {
1343+ /// # fn from(value: &str) -> Self {
1344+ /// # TestError {}
1345+ /// # }
1346+ /// # }
1347+ ///
1348+ /// # fn run() -> Result<(), TestError> {
13161349 /// let url = Url::parse("https://example.com/foo/bar")?;
13171350 /// let mut path_segments = url.path_segments().ok_or_else(|| "cannot be base")?;
13181351 /// assert_eq!(path_segments.next(), Some("foo"));
@@ -1717,9 +1750,22 @@ impl Url {
17171750 ///
17181751 /// ```
17191752 /// use url::Url;
1720- /// # use std::error::Error;
1753+ /// # use url::ParseError;
1754+ /// # #[derive(Debug)]
1755+ /// # /// A simple wrapper error struct for `no_std` support
1756+ /// # struct TestError;
1757+ /// # impl From<ParseError> for TestError {
1758+ /// # fn from(value: ParseError) -> Self {
1759+ /// # TestError {}
1760+ /// # }
1761+ /// # }
1762+ /// # impl From<&str> for TestError {
1763+ /// # fn from(value: &str) -> Self {
1764+ /// # TestError {}
1765+ /// # }
1766+ /// # }
17211767 ///
1722- /// # fn run() -> Result<(), Box<dyn Error> > {
1768+ /// # fn run() -> Result<(), TestError > {
17231769 /// let mut url = Url::parse("ssh://example.net:2048/")?;
17241770 ///
17251771 /// url.set_port(Some(4096)).map_err(|_| "cannot be base")?;
@@ -1736,9 +1782,22 @@ impl Url {
17361782 ///
17371783 /// ```rust
17381784 /// use url::Url;
1739- /// # use std::error::Error;
1785+ /// # use url::ParseError;
1786+ /// # #[derive(Debug)]
1787+ /// # /// A simple wrapper error struct for `no_std` support
1788+ /// # struct TestError;
1789+ /// # impl From<ParseError> for TestError {
1790+ /// # fn from(value: ParseError) -> Self {
1791+ /// # TestError {}
1792+ /// # }
1793+ /// # }
1794+ /// # impl From<&str> for TestError {
1795+ /// # fn from(value: &str) -> Self {
1796+ /// # TestError {}
1797+ /// # }
1798+ /// # }
17401799 ///
1741- /// # fn run() -> Result<(), Box<dyn Error> > {
1800+ /// # fn run() -> Result<(), TestError > {
17421801 /// let mut url = Url::parse("https://example.org/")?;
17431802 ///
17441803 /// url.set_port(Some(443)).map_err(|_| "cannot be base")?;
@@ -2419,7 +2478,12 @@ impl Url {
24192478 /// # run().unwrap();
24202479 /// # }
24212480 /// ```
2422- #[ cfg( any( unix, windows, target_os = "redox" , target_os = "wasi" ) ) ]
2481+ ///
2482+ /// This method is only available if the `std` Cargo feature is enabled.
2483+ #[ cfg( all(
2484+ feature = "std" ,
2485+ any( unix, windows, target_os = "redox" , target_os = "wasi" )
2486+ ) ) ]
24232487 #[ allow( clippy:: result_unit_err) ]
24242488 pub fn from_file_path < P : AsRef < Path > > ( path : P ) -> Result < Url , ( ) > {
24252489 let mut serialization = "file://" . to_owned ( ) ;
@@ -2456,7 +2520,12 @@ impl Url {
24562520 ///
24572521 /// Note that `std::path` does not consider trailing slashes significant
24582522 /// and usually does not include them (e.g. in `Path::parent()`).
2459- #[ cfg( any( unix, windows, target_os = "redox" , target_os = "wasi" ) ) ]
2523+ ///
2524+ /// This method is only available if the `std` Cargo feature is enabled.
2525+ #[ cfg( all(
2526+ feature = "std" ,
2527+ any( unix, windows, target_os = "redox" , target_os = "wasi" )
2528+ ) ) ]
24602529 #[ allow( clippy:: result_unit_err) ]
24612530 pub fn from_directory_path < P : AsRef < Path > > ( path : P ) -> Result < Url , ( ) > {
24622531 let mut url = Url :: from_file_path ( path) ?;
@@ -2572,8 +2641,13 @@ impl Url {
25722641 /// or if `Path::new_opt()` returns `None`.
25732642 /// (That is, if the percent-decoded path contains a NUL byte or,
25742643 /// for a Windows path, is not UTF-8.)
2644+ ///
2645+ /// This method is only available if the `std` Cargo feature is enabled.
25752646 #[ inline]
2576- #[ cfg( any( unix, windows, target_os = "redox" , target_os = "wasi" ) ) ]
2647+ #[ cfg( all(
2648+ feature = "std" ,
2649+ any( unix, windows, target_os = "redox" , target_os = "wasi" )
2650+ ) ) ]
25772651 #[ allow( clippy:: result_unit_err) ]
25782652 pub fn to_file_path ( & self ) -> Result < PathBuf , ( ) > {
25792653 if let Some ( segments) = self . path_segments ( ) {
@@ -2777,11 +2851,13 @@ impl<'de> serde::Deserialize<'de> for Url {
27772851 }
27782852}
27792853
2780- #[ cfg( any( unix, target_os = "redox" , target_os = "wasi" ) ) ]
2854+ #[ cfg( all ( feature = "std" , any( unix, target_os = "redox" , target_os = "wasi" ) ) ) ]
27812855fn path_to_file_url_segments (
27822856 path : & Path ,
27832857 serialization : & mut String ,
27842858) -> Result < ( u32 , HostInternal ) , ( ) > {
2859+ use crate :: parser:: PATH_SEGMENT ;
2860+ use percent_encoding:: percent_encode;
27852861 #[ cfg( any( unix, target_os = "redox" ) ) ]
27862862 use std:: os:: unix:: prelude:: OsStrExt ;
27872863 #[ cfg( target_os = "wasi" ) ]
@@ -2807,20 +2883,23 @@ fn path_to_file_url_segments(
28072883 Ok ( ( host_end, HostInternal :: None ) )
28082884}
28092885
2810- #[ cfg( windows) ]
2886+ #[ cfg( all ( feature = "std" , windows) ) ]
28112887fn path_to_file_url_segments (
28122888 path : & Path ,
28132889 serialization : & mut String ,
28142890) -> Result < ( u32 , HostInternal ) , ( ) > {
28152891 path_to_file_url_segments_windows ( path, serialization)
28162892}
28172893
2894+ #[ cfg( feature = "std" ) ]
28182895// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
28192896#[ cfg_attr( not( windows) , allow( dead_code) ) ]
28202897fn path_to_file_url_segments_windows (
28212898 path : & Path ,
28222899 serialization : & mut String ,
28232900) -> Result < ( u32 , HostInternal ) , ( ) > {
2901+ use crate :: parser:: PATH_SEGMENT ;
2902+ use percent_encoding:: percent_encode;
28242903 use std:: path:: { Component , Prefix } ;
28252904 if !path. is_absolute ( ) {
28262905 return Err ( ( ) ) ;
@@ -2879,11 +2958,13 @@ fn path_to_file_url_segments_windows(
28792958 Ok ( ( host_end, host_internal) )
28802959}
28812960
2882- #[ cfg( any( unix, target_os = "redox" , target_os = "wasi" ) ) ]
2961+ #[ cfg( all ( feature = "std" , any( unix, target_os = "redox" , target_os = "wasi" ) ) ) ]
28832962fn file_url_segments_to_pathbuf (
28842963 host : Option < & str > ,
28852964 segments : str:: Split < ' _ , char > ,
28862965) -> Result < PathBuf , ( ) > {
2966+ use alloc:: vec:: Vec ;
2967+ use percent_encoding:: percent_decode;
28872968 use std:: ffi:: OsStr ;
28882969 #[ cfg( any( unix, target_os = "redox" ) ) ]
28892970 use std:: os:: unix:: prelude:: OsStrExt ;
@@ -2924,20 +3005,22 @@ fn file_url_segments_to_pathbuf(
29243005 Ok ( path)
29253006}
29263007
2927- #[ cfg( windows) ]
3008+ #[ cfg( all ( feature = "std" , windows) ) ]
29283009fn file_url_segments_to_pathbuf (
29293010 host : Option < & str > ,
29303011 segments : str:: Split < char > ,
29313012) -> Result < PathBuf , ( ) > {
29323013 file_url_segments_to_pathbuf_windows ( host, segments)
29333014}
29343015
3016+ #[ cfg( feature = "std" ) ]
29353017// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
29363018#[ cfg_attr( not( windows) , allow( dead_code) ) ]
29373019fn file_url_segments_to_pathbuf_windows (
29383020 host : Option < & str > ,
29393021 mut segments : str:: Split < ' _ , char > ,
29403022) -> Result < PathBuf , ( ) > {
3023+ use percent_encoding:: percent_decode;
29413024 let mut string = if let Some ( host) = host {
29423025 r"\\" . to_owned ( ) + host
29433026 } else {
0 commit comments