@@ -127,27 +127,44 @@ url = { version = "2", features = ["serde"] }
127
127
feature( debugger_visualizer) ,
128
128
debugger_visualizer( natvis_file = "../../debug_metadata/url.natvis" )
129
129
) ]
130
+ #![ no_std]
130
131
131
132
pub use form_urlencoded;
132
133
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
+
133
144
#[ cfg( feature = "serde" ) ]
134
145
extern crate serde;
135
146
136
147
use 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
+ } ;
151
168
152
169
pub use crate :: host:: Host ;
153
170
pub use crate :: origin:: { OpaqueOrigin , Origin } ;
@@ -1237,10 +1254,11 @@ impl Url {
1237
1254
/// })
1238
1255
/// }
1239
1256
/// ```
1257
+ #[ cfg( feature = "std" ) ]
1240
1258
pub fn socket_addrs (
1241
1259
& self ,
1242
1260
default_port_number : impl Fn ( ) -> Option < u16 > ,
1243
- ) -> io:: Result < Vec < SocketAddr > > {
1261
+ ) -> io:: Result < alloc :: vec :: Vec < SocketAddr > > {
1244
1262
// Note: trying to avoid the Vec allocation by returning `impl AsRef<[SocketAddr]>`
1245
1263
// causes borrowck issues because the return value borrows `default_port_number`:
1246
1264
//
@@ -1249,6 +1267,7 @@ impl Url {
1249
1267
// > This RFC proposes that *all* type parameters are considered in scope
1250
1268
// > for `impl Trait` in return position
1251
1269
1270
+ // TODO: Return custom error type to support no_std
1252
1271
fn io_result < T > ( opt : Option < T > , message : & str ) -> io:: Result < T > {
1253
1272
opt. ok_or_else ( || io:: Error :: new ( io:: ErrorKind :: InvalidData , message) )
1254
1273
}
@@ -1310,9 +1329,23 @@ impl Url {
1310
1329
///
1311
1330
/// ```
1312
1331
/// use url::Url;
1313
- /// # use std::error::Error;
1314
1332
///
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> {
1316
1349
/// let url = Url::parse("https://example.com/foo/bar")?;
1317
1350
/// let mut path_segments = url.path_segments().ok_or_else(|| "cannot be base")?;
1318
1351
/// assert_eq!(path_segments.next(), Some("foo"));
@@ -1717,9 +1750,22 @@ impl Url {
1717
1750
///
1718
1751
/// ```
1719
1752
/// 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
+ /// # }
1721
1767
///
1722
- /// # fn run() -> Result<(), Box<dyn Error> > {
1768
+ /// # fn run() -> Result<(), TestError > {
1723
1769
/// let mut url = Url::parse("ssh://example.net:2048/")?;
1724
1770
///
1725
1771
/// url.set_port(Some(4096)).map_err(|_| "cannot be base")?;
@@ -1736,9 +1782,22 @@ impl Url {
1736
1782
///
1737
1783
/// ```rust
1738
1784
/// 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
+ /// # }
1740
1799
///
1741
- /// # fn run() -> Result<(), Box<dyn Error> > {
1800
+ /// # fn run() -> Result<(), TestError > {
1742
1801
/// let mut url = Url::parse("https://example.org/")?;
1743
1802
///
1744
1803
/// url.set_port(Some(443)).map_err(|_| "cannot be base")?;
@@ -2419,7 +2478,12 @@ impl Url {
2419
2478
/// # run().unwrap();
2420
2479
/// # }
2421
2480
/// ```
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
+ ) ) ]
2423
2487
#[ allow( clippy:: result_unit_err) ]
2424
2488
pub fn from_file_path < P : AsRef < Path > > ( path : P ) -> Result < Url , ( ) > {
2425
2489
let mut serialization = "file://" . to_owned ( ) ;
@@ -2456,7 +2520,12 @@ impl Url {
2456
2520
///
2457
2521
/// Note that `std::path` does not consider trailing slashes significant
2458
2522
/// 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
+ ) ) ]
2460
2529
#[ allow( clippy:: result_unit_err) ]
2461
2530
pub fn from_directory_path < P : AsRef < Path > > ( path : P ) -> Result < Url , ( ) > {
2462
2531
let mut url = Url :: from_file_path ( path) ?;
@@ -2572,8 +2641,13 @@ impl Url {
2572
2641
/// or if `Path::new_opt()` returns `None`.
2573
2642
/// (That is, if the percent-decoded path contains a NUL byte or,
2574
2643
/// for a Windows path, is not UTF-8.)
2644
+ ///
2645
+ /// This method is only available if the `std` Cargo feature is enabled.
2575
2646
#[ 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
+ ) ) ]
2577
2651
#[ allow( clippy:: result_unit_err) ]
2578
2652
pub fn to_file_path ( & self ) -> Result < PathBuf , ( ) > {
2579
2653
if let Some ( segments) = self . path_segments ( ) {
@@ -2777,11 +2851,13 @@ impl<'de> serde::Deserialize<'de> for Url {
2777
2851
}
2778
2852
}
2779
2853
2780
- #[ cfg( any( unix, target_os = "redox" , target_os = "wasi" ) ) ]
2854
+ #[ cfg( all ( feature = "std" , any( unix, target_os = "redox" , target_os = "wasi" ) ) ) ]
2781
2855
fn path_to_file_url_segments (
2782
2856
path : & Path ,
2783
2857
serialization : & mut String ,
2784
2858
) -> Result < ( u32 , HostInternal ) , ( ) > {
2859
+ use crate :: parser:: PATH_SEGMENT ;
2860
+ use percent_encoding:: percent_encode;
2785
2861
#[ cfg( any( unix, target_os = "redox" ) ) ]
2786
2862
use std:: os:: unix:: prelude:: OsStrExt ;
2787
2863
#[ cfg( target_os = "wasi" ) ]
@@ -2807,20 +2883,23 @@ fn path_to_file_url_segments(
2807
2883
Ok ( ( host_end, HostInternal :: None ) )
2808
2884
}
2809
2885
2810
- #[ cfg( windows) ]
2886
+ #[ cfg( all ( feature = "std" , windows) ) ]
2811
2887
fn path_to_file_url_segments (
2812
2888
path : & Path ,
2813
2889
serialization : & mut String ,
2814
2890
) -> Result < ( u32 , HostInternal ) , ( ) > {
2815
2891
path_to_file_url_segments_windows ( path, serialization)
2816
2892
}
2817
2893
2894
+ #[ cfg( feature = "std" ) ]
2818
2895
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
2819
2896
#[ cfg_attr( not( windows) , allow( dead_code) ) ]
2820
2897
fn path_to_file_url_segments_windows (
2821
2898
path : & Path ,
2822
2899
serialization : & mut String ,
2823
2900
) -> Result < ( u32 , HostInternal ) , ( ) > {
2901
+ use crate :: parser:: PATH_SEGMENT ;
2902
+ use percent_encoding:: percent_encode;
2824
2903
use std:: path:: { Component , Prefix } ;
2825
2904
if !path. is_absolute ( ) {
2826
2905
return Err ( ( ) ) ;
@@ -2879,11 +2958,13 @@ fn path_to_file_url_segments_windows(
2879
2958
Ok ( ( host_end, host_internal) )
2880
2959
}
2881
2960
2882
- #[ cfg( any( unix, target_os = "redox" , target_os = "wasi" ) ) ]
2961
+ #[ cfg( all ( feature = "std" , any( unix, target_os = "redox" , target_os = "wasi" ) ) ) ]
2883
2962
fn file_url_segments_to_pathbuf (
2884
2963
host : Option < & str > ,
2885
2964
segments : str:: Split < ' _ , char > ,
2886
2965
) -> Result < PathBuf , ( ) > {
2966
+ use alloc:: vec:: Vec ;
2967
+ use percent_encoding:: percent_decode;
2887
2968
use std:: ffi:: OsStr ;
2888
2969
#[ cfg( any( unix, target_os = "redox" ) ) ]
2889
2970
use std:: os:: unix:: prelude:: OsStrExt ;
@@ -2924,20 +3005,22 @@ fn file_url_segments_to_pathbuf(
2924
3005
Ok ( path)
2925
3006
}
2926
3007
2927
- #[ cfg( windows) ]
3008
+ #[ cfg( all ( feature = "std" , windows) ) ]
2928
3009
fn file_url_segments_to_pathbuf (
2929
3010
host : Option < & str > ,
2930
3011
segments : str:: Split < char > ,
2931
3012
) -> Result < PathBuf , ( ) > {
2932
3013
file_url_segments_to_pathbuf_windows ( host, segments)
2933
3014
}
2934
3015
3016
+ #[ cfg( feature = "std" ) ]
2935
3017
// Build this unconditionally to alleviate https://github.com/servo/rust-url/issues/102
2936
3018
#[ cfg_attr( not( windows) , allow( dead_code) ) ]
2937
3019
fn file_url_segments_to_pathbuf_windows (
2938
3020
host : Option < & str > ,
2939
3021
mut segments : str:: Split < ' _ , char > ,
2940
3022
) -> Result < PathBuf , ( ) > {
3023
+ use percent_encoding:: percent_decode;
2941
3024
let mut string = if let Some ( host) = host {
2942
3025
r"\\" . to_owned ( ) + host
2943
3026
} else {
0 commit comments