@@ -133,7 +133,12 @@ struct ParseError {
133
133
}
134
134
135
135
impl ParseError {
136
- fn new ( file : & str , reason : & str ) -> Self {
136
+ fn new ( item : & str , reason : & str ) -> Self {
137
+ ParseError {
138
+ reason : format ! ( "Error parsing {}: {}" , item, reason) ,
139
+ }
140
+ }
141
+ fn in_file ( file : & str , reason : & str ) -> Self {
137
142
ParseError {
138
143
reason : format ! ( "Error parsing /proc/[pid]/{}: {}" , file, reason) ,
139
144
}
@@ -182,7 +187,7 @@ impl ProcStat {
182
187
let s: String = s?;
183
188
let substrs = s. splitn ( 2 , ":" ) . collect :: < Vec < & str > > ( ) ;
184
189
if substrs. len ( ) < 2 {
185
- Err ( ParseError :: new (
190
+ Err ( ParseError :: in_file (
186
191
"status" ,
187
192
& format ! (
188
193
"Fewer fields than expected in line '{}' of file {}" ,
@@ -208,7 +213,7 @@ impl ProcStat {
208
213
fn get_field ( & self , field : & str ) -> Result < & str , Box < Error > > {
209
214
match self . fields . get ( field) {
210
215
Some ( val) => Ok ( val) ,
211
- None => Err ( From :: from ( ParseError :: new (
216
+ None => Err ( From :: from ( ParseError :: in_file (
212
217
"status" ,
213
218
& format ! (
214
219
"Missing expected field '{}' file {}" ,
@@ -646,17 +651,27 @@ fn parse_sock_type(type_code: &str) -> SockType {
646
651
}
647
652
}
648
653
649
- // Parse a socket address of the form "0100007F:1538" (i.e. 127.0.0.1:1538)
650
- fn parse_ipv4_sock_addr ( s : & str ) -> Result < SocketAddr , Box < Error > > {
651
- let port = u16:: from_str_radix ( s. split ( ':' ) . collect :: < Vec < & str > > ( ) [ 1 ] , 16 ) . unwrap ( ) ;
652
- let addr = u32:: from_str_radix ( s. split ( ':' ) . collect :: < Vec < & str > > ( ) [ 0 ] , 16 ) . unwrap ( ) ;
653
- // TODO do we need to change 'addr' to network order?
654
- let addr = Ipv4Addr :: new (
655
- ( ( addr >> 24 ) & 0xFF ) as u8 ,
656
- ( ( addr >> 16 ) & 0xFF ) as u8 ,
657
- ( ( addr >> 8 ) & 0xFF ) as u8 ,
658
- ( addr & 0xFF ) as u8 ,
659
- ) ;
654
+ // Parse a socket address of the form "0100007F:1538" (i.e. 127.0.0.1:5432)
655
+ fn parse_ipv4_sock_addr ( s : & str ) -> Result < SocketAddr , ParseError > {
656
+ let mk_err = || {
657
+ ParseError :: new (
658
+ "IPv4 address" ,
659
+ & format ! ( "expected address in form '0100007F:1538', got {}" , s) ,
660
+ )
661
+ } ;
662
+
663
+ let fields = s. split ( ':' ) . collect :: < Vec < _ > > ( ) ;
664
+ if fields. len ( ) != 2 {
665
+ return Err ( mk_err ( ) ) ;
666
+ }
667
+
668
+ // Port is always printed with most-significant byte first.
669
+ let port = u16:: from_str_radix ( fields[ 1 ] , 16 ) . map_err ( |_| mk_err ( ) ) ?;
670
+
671
+ // Address is printed with most-significant byte first on big-endian systems and vice-versa on
672
+ // little-endian systems.
673
+ let addr_native_endian = u32:: from_str_radix ( fields[ 0 ] , 16 ) . map_err ( |_| mk_err ( ) ) ?;
674
+ let addr = Ipv4Addr :: from ( addr_native_endian. to_be ( ) ) ;
660
675
661
676
Ok ( SocketAddr :: new ( IpAddr :: V4 ( addr) , port) )
662
677
}
@@ -916,3 +931,20 @@ pub fn ptree_main() {
916
931
}
917
932
}
918
933
}
934
+
935
+ mod test {
936
+ use super :: * ;
937
+ use std:: net:: SocketAddr ;
938
+
939
+ #[ test]
940
+ fn test_parse_ipv4_sock_addr ( ) {
941
+ assert_eq ! (
942
+ parse_ipv4_sock_addr( "0100007F:1538" ) . unwrap( ) ,
943
+ "127.0.0.1:5432" . parse:: <SocketAddr >( ) . unwrap( )
944
+ ) ;
945
+
946
+ assert ! ( parse_ipv4_sock_addr( "0100007F 1538" ) . is_err( ) ) ;
947
+ assert ! ( parse_ipv4_sock_addr( "010000YY:1538" ) . is_err( ) ) ;
948
+ assert ! ( parse_ipv4_sock_addr( "0100007F:15YY" ) . is_err( ) ) ;
949
+ }
950
+ }
0 commit comments