11use crate :: { borrowed, bstr:: ByteSlice , Protocol } ;
22use bstr:: BStr ;
33use nom:: {
4- bytes:: complete:: { tag, take_till1, take_while1} ,
4+ bytes:: complete:: { tag, take_till1, take_while , take_while1} ,
55 character:: complete:: alphanumeric1,
6- combinator:: recognize,
6+ combinator:: { opt , recognize} ,
77 sequence:: tuple,
88 IResult , Parser ,
99} ;
1010
1111mod error;
1212pub use error:: Error ;
13+ use nom:: character:: is_digit;
14+ use nom:: combinator:: map_res;
15+ use nom:: sequence:: preceded;
1316
1417fn protocol ( i : & [ u8 ] ) -> IResult < & [ u8 ] , Protocol , Error > {
1518 tag ( b"ssh://" )
@@ -26,16 +29,25 @@ fn host(i: &[u8]) -> IResult<&[u8], &BStr, Error> {
2629
2730fn path ( i : & [ u8 ] ) -> IResult < & [ u8 ] , & BStr , Error > {
2831 // TODO: be much less permissive
29- take_while1 ( |_| true ) . map ( |path : & [ u8 ] | path. as_bstr ( ) ) . parse ( i)
32+ recognize ( preceded ( tag ( b"/" ) , take_while ( |_| true ) ) )
33+ . map ( |path : & [ u8 ] | path. as_bstr ( ) )
34+ . parse ( i)
35+ . map_err ( Error :: context ( "paths cannot be empty and start with '/'" ) )
36+ }
37+
38+ fn port ( i : & [ u8 ] ) -> IResult < & [ u8 ] , u32 , Error > {
39+ map_res ( preceded ( tag ( b":" ) , take_while1 ( is_digit) ) , |input : & [ u8 ] | {
40+ btoi:: btoi ( input)
41+ } ) ( i)
3042}
3143
3244fn full_url ( i : & [ u8 ] ) -> IResult < & [ u8 ] , borrowed:: Url , Error > {
33- tuple ( ( protocol, host, path) )
34- . map ( |( proto, host, path) | borrowed:: Url {
45+ tuple ( ( protocol, host, opt ( port ) , path) )
46+ . map ( |( proto, host, port , path) | borrowed:: Url {
3547 protocol : proto,
3648 user : None ,
3749 host : Some ( host) ,
38- port : None ,
50+ port,
3951 path,
4052 expand_user : None ,
4153 } )
0 commit comments