1
- // Clippy gives us a false possitive on FromPrimitive/ToPrimitive derives.
2
- // This is fixed on rust-clippy#3932.
3
- // TODO: remove this on the next clippy release.
4
- #![ allow( clippy:: useless_attribute) ]
5
-
6
- use bytes:: Buf ;
7
- use failure:: ResultExt ;
8
- use memchr:: memchr;
9
- use num_derive:: { FromPrimitive , ToPrimitive } ;
10
- use num_traits:: { FromPrimitive , ToPrimitive } ;
11
- use std:: io:: Cursor ;
1
+ // clippy finds redundant closures in nom macros.
2
+ // allow this until it is fixed in nom.
3
+ #![ allow( clippy:: redundant_closure) ]
4
+
5
+ use bytes:: BufMut ;
6
+ use nom:: be_u16;
12
7
use std:: str:: { self , FromStr } ;
13
8
14
9
use crate :: error:: * ;
15
10
16
- #[ derive( Debug ) ]
11
+ const RRQ : u16 = 1 ;
12
+ const WRQ : u16 = 2 ;
13
+ const DATA : u16 = 3 ;
14
+ const ACK : u16 = 4 ;
15
+ const ERROR : u16 = 5 ;
16
+
17
+ #[ derive( Debug , PartialEq ) ]
17
18
pub enum Packet {
18
19
Rrq ( String , Mode ) ,
19
20
Wrq ( String , Mode ) ,
@@ -22,20 +23,120 @@ pub enum Packet {
22
23
Error ( u16 , String ) ,
23
24
}
24
25
25
- #[ derive( Debug ) ]
26
+ #[ derive( Debug , PartialEq ) ]
26
27
pub enum Mode {
27
28
Netascii ,
28
29
Octet ,
29
30
Mail ,
30
31
}
31
32
32
- #[ derive( Debug , FromPrimitive , ToPrimitive ) ]
33
- pub enum OpCode {
34
- Rrq = 1 ,
35
- Wrq = 2 ,
36
- Data = 3 ,
37
- Ack = 4 ,
38
- Error = 5 ,
33
+ fn take_512_max ( i : & [ u8 ] ) -> nom:: IResult < & [ u8 ] , & [ u8 ] > {
34
+ if i. len ( ) <= 512 {
35
+ Ok ( ( & [ ] , i) )
36
+ } else {
37
+ Ok ( ( & i[ 512 ..] , & i[ ..512 ] ) )
38
+ }
39
+ }
40
+
41
+ named ! ( nul_string<& [ u8 ] , & str >,
42
+ do_parse!(
43
+ s: map_res!( take_till!( |ch| ch == b'\0' ) , str :: from_utf8) >>
44
+ take!( 1 ) >>
45
+
46
+ ( s)
47
+ )
48
+ ) ;
49
+
50
+ named ! ( filename_mode<& [ u8 ] , ( & str , Mode ) >,
51
+ do_parse!(
52
+ filename: nul_string >>
53
+ mode: alt!(
54
+ tag_no_case!( "netascii" ) |
55
+ tag_no_case!( "octet" ) |
56
+ tag_no_case!( "mail" )
57
+ ) >>
58
+ tag!( "\0 " ) >>
59
+
60
+ ( {
61
+ let mode = str :: from_utf8( mode) . unwrap( ) ;
62
+ let mode = Mode :: from_str( mode) . unwrap( ) ;
63
+ ( filename, mode)
64
+ } )
65
+ )
66
+ ) ;
67
+
68
+ named ! ( rrq<& [ u8 ] , Packet >,
69
+ do_parse!(
70
+ fm: filename_mode >>
71
+
72
+ ( {
73
+ let ( filename, mode) = fm;
74
+ Packet :: Rrq ( filename. to_owned( ) , mode)
75
+ } )
76
+ )
77
+ ) ;
78
+
79
+ named ! ( wrq<& [ u8 ] , Packet >,
80
+ do_parse!(
81
+ fm: filename_mode >>
82
+
83
+ ( {
84
+ let ( filename, mode) = fm;
85
+ Packet :: Wrq ( filename. to_owned( ) , mode)
86
+ } )
87
+ )
88
+ ) ;
89
+
90
+ named ! ( data<& [ u8 ] , Packet >,
91
+ do_parse!(
92
+ block: be_u16 >>
93
+ data: take_512_max >>
94
+
95
+ ( Packet :: Data ( block, data. to_vec( ) ) )
96
+ )
97
+ ) ;
98
+
99
+ named ! ( ack<& [ u8 ] , Packet >,
100
+ do_parse!(
101
+ block: be_u16 >>
102
+
103
+ ( Packet :: Ack ( block) )
104
+ )
105
+ ) ;
106
+
107
+ named ! ( error<& [ u8 ] , Packet >,
108
+ do_parse!(
109
+ code: be_u16 >>
110
+ msg: nul_string >>
111
+
112
+ ( Packet :: Error ( code, msg. to_owned( ) ) )
113
+ )
114
+ ) ;
115
+
116
+ named ! ( packet<& [ u8 ] , Packet >,
117
+ do_parse!(
118
+ packet: switch!( be_u16,
119
+ RRQ => call!( rrq) |
120
+ WRQ => call!( wrq) |
121
+ DATA => call!( data) |
122
+ ACK => call!( ack) |
123
+ ERROR => call!( error)
124
+ ) >>
125
+
126
+ ( packet)
127
+ )
128
+ ) ;
129
+
130
+ impl Packet {
131
+ pub fn from_bytes ( data : & [ u8 ] ) -> Result < Packet > {
132
+ let ( rest, p) = packet ( data) . map_err ( |_| Error :: from ( ErrorKind :: InvalidPacket ) ) ?;
133
+
134
+ if rest. is_empty ( ) {
135
+ Ok ( p)
136
+ } else {
137
+ Err ( ErrorKind :: PacketTooLarge . into ( ) )
138
+ }
139
+ }
39
140
}
40
141
41
142
impl Mode {
@@ -56,111 +157,7 @@ impl FromStr for Mode {
56
157
"netascii" => Ok ( Mode :: Netascii ) ,
57
158
"octet" => Ok ( Mode :: Octet ) ,
58
159
"mail" => Ok ( Mode :: Mail ) ,
59
- _ => Err ( ErrorKind :: DecodeError ( "Invalid mode" ) . into ( ) ) ,
160
+ _ => Err ( ErrorKind :: InvalidMode . into ( ) ) ,
60
161
}
61
162
}
62
163
}
63
-
64
- fn read_string ( buf : & mut Cursor < & [ u8 ] > ) -> Result < String > {
65
- let b = buf. bytes ( ) ;
66
-
67
- let pos =
68
- memchr ( 0 , b) . ok_or_else ( || Error :: from ( ErrorKind :: DecodeError ( "No string ending" ) ) ) ?;
69
-
70
- let s = str:: from_utf8 ( & b[ ..pos] )
71
- . context ( ErrorKind :: DecodeError ( "Invalid UTF-8 string" ) ) ?
72
- . to_string ( ) ;
73
-
74
- buf. advance ( pos + 1 ) ;
75
-
76
- Ok ( s)
77
- }
78
-
79
- impl Packet {
80
- pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < Self > {
81
- let mut buf = Cursor :: new ( bytes) ;
82
-
83
- if buf. remaining ( ) < 2 {
84
- return Err ( ErrorKind :: DecodeError ( "Insufficient packet length" ) . into ( ) ) ;
85
- }
86
-
87
- match FromPrimitive :: from_u16 ( buf. get_u16_be ( ) ) {
88
- Some ( OpCode :: Rrq ) => {
89
- let filename = read_string ( & mut buf) ?;
90
- let mode = Mode :: from_str ( read_string ( & mut buf) ?. as_str ( ) ) ?;
91
- Ok ( Packet :: Rrq ( filename, mode) )
92
- }
93
- Some ( OpCode :: Wrq ) => {
94
- let filename = read_string ( & mut buf) ?;
95
- let mode = Mode :: from_str ( read_string ( & mut buf) ?. as_str ( ) ) ?;
96
- Ok ( Packet :: Wrq ( filename, mode) )
97
- }
98
- Some ( OpCode :: Data ) => {
99
- if buf. remaining ( ) < 2 {
100
- return Err ( ErrorKind :: DecodeError ( "Insufficient packet length" ) . into ( ) ) ;
101
- }
102
- let block_nr = buf. get_u16_be ( ) ;
103
- let data = buf. collect ( ) ;
104
- Ok ( Packet :: Data ( block_nr, data) )
105
- }
106
- Some ( OpCode :: Ack ) => {
107
- if buf. remaining ( ) < 2 {
108
- return Err ( ErrorKind :: DecodeError ( "Insufficient packet length" ) . into ( ) ) ;
109
- }
110
- let block_nr = buf. get_u16_be ( ) ;
111
- Ok ( Packet :: Ack ( block_nr) )
112
- }
113
- Some ( OpCode :: Error ) => {
114
- if buf. remaining ( ) < 2 {
115
- return Err ( ErrorKind :: DecodeError ( "Insufficient packet length" ) . into ( ) ) ;
116
- }
117
- let code = buf. get_u16_be ( ) ;
118
- let msg = read_string ( & mut buf) ?;
119
- Ok ( Packet :: Error ( code, msg) )
120
- }
121
- None => Err ( ErrorKind :: DecodeError ( "Invalid opcode" ) . into ( ) ) ,
122
- }
123
- }
124
-
125
- pub fn to_bytes ( & self ) -> Option < Vec < u8 > > {
126
- let mut buf = Vec :: new ( ) ;
127
-
128
- match self {
129
- Packet :: Rrq ( filename, mode) => {
130
- let opcode = ToPrimitive :: to_u16 ( & OpCode :: Rrq ) ?. to_be_bytes ( ) ;
131
- buf. extend_from_slice ( & opcode[ ..] ) ;
132
- buf. extend_from_slice ( filename. as_bytes ( ) ) ;
133
- buf. push ( 0 ) ;
134
- buf. extend_from_slice ( mode. to_str ( ) . as_bytes ( ) ) ;
135
- buf. push ( 0 ) ;
136
- Some ( buf)
137
- }
138
- Packet :: Wrq ( filename, mode) => {
139
- let opcode = ToPrimitive :: to_u16 ( & OpCode :: Wrq ) ?. to_be_bytes ( ) ;
140
- buf. extend_from_slice ( & opcode[ ..] ) ;
141
- buf. extend_from_slice ( filename. as_bytes ( ) ) ;
142
- buf. push ( 0 ) ;
143
- buf. extend_from_slice ( mode. to_str ( ) . as_bytes ( ) ) ;
144
- buf. push ( 0 ) ;
145
- Some ( buf)
146
- }
147
- _ => unimplemented ! ( ) ,
148
- }
149
- }
150
- }
151
-
152
- #[ cfg( test) ]
153
- mod tests {
154
- use super :: * ;
155
- use bytes:: IntoBuf ;
156
-
157
- #[ test]
158
- fn check ( ) {
159
- let mut b = b"abc\0 def\0 " . into_buf ( ) ;
160
-
161
- assert_eq ! ( read_string( & mut b) , Ok ( "abc" . to_string( ) ) ) ;
162
- assert_eq ! ( read_string( & mut b) , Ok ( "def" . to_string( ) ) ) ;
163
-
164
- //let b = Packet::from_buf(vec![1u8]).expect("XXX");
165
- }
166
- }
0 commit comments