1- use bytes:: BytesMut ;
1+ use bytes:: { Buf , BytesMut } ;
22use futures:: prelude:: * ;
33use futures:: sink:: SinkExt ;
44
55use tokio:: net:: TcpStream ;
66use tokio_util:: codec:: { Decoder , Encoder , Framed } ;
77use winnow:: error:: ErrMode ;
8+ use winnow:: stream:: Offset ;
9+ use winnow:: Partial ;
810
911pub type ClientTransport = Framed < TcpStream , ClientCodec > ;
1012
@@ -75,11 +77,14 @@ impl Decoder for ClientCodec {
7577 type Error = anyhow:: Error ;
7678
7779 fn decode ( & mut self , src : & mut BytesMut ) -> Result < Option < Self :: Item > > {
78- let item = match frame:: parse_frame ( & mut & src[ ..] ) {
80+ let buf = & mut Partial :: new ( src. chunk ( ) ) ;
81+ let item = match frame:: parse_frame ( buf) {
7982 Ok ( frame) => Message :: < FromServer > :: from_frame ( frame) ,
8083 Err ( ErrMode :: Incomplete ( _) ) => return Ok ( None ) ,
8184 Err ( e) => bail ! ( "Parse failed: {:?}" , e) ,
8285 } ;
86+ let len = buf. offset_from ( & Partial :: new ( src. chunk ( ) ) ) ;
87+ src. advance ( len) ;
8388 item. map ( Some )
8489 }
8590}
@@ -96,3 +101,155 @@ impl Encoder<Message<ToServer>> for ClientCodec {
96101 Ok ( ( ) )
97102 }
98103}
104+
105+ #[ cfg( test) ]
106+ mod tests {
107+ use std:: time:: Duration ;
108+
109+ use futures:: { future:: ok, SinkExt , StreamExt , TryStreamExt } ;
110+
111+ use crate :: { client, FromServer , ToServer } ;
112+
113+ // Test to send a message
114+ #[ tokio:: test]
115+ #[ ignore]
116+ async fn test_session ( ) {
117+ let mut conn = crate :: client:: connect (
118+ "localhost:61613" ,
119+ "/" ,
120+ //None,None
121+ Some ( "artemis" . to_string ( ) ) ,
122+ Some ( "artemis" . to_string ( ) ) ,
123+ )
124+ . await
125+ . expect ( "Default connection to localhost" ) ;
126+ let msg = crate :: Message {
127+ content : ToServer :: Send {
128+ destination : "/test/a" . to_string ( ) ,
129+ transaction : None ,
130+ headers : Some ( vec ! [ ( "header-a" . to_string( ) , "value-a" . to_string( ) ) ] ) ,
131+ body : Some ( "This is a test message" . as_bytes ( ) . to_vec ( ) ) ,
132+ } ,
133+ extra_headers : vec ! [ ] ,
134+ } ;
135+ conn. send ( msg) . await . expect ( "Send a" ) ;
136+ let msg = crate :: Message {
137+ content : ToServer :: Send {
138+ destination : "/test/b" . to_string ( ) ,
139+ transaction : None ,
140+ headers : Some ( vec ! [ ( "header-b" . to_string( ) , "value-b" . to_string( ) ) ] ) ,
141+ body : Some ( "This is a another test message" . as_bytes ( ) . to_vec ( ) ) ,
142+ } ,
143+ extra_headers : vec ! [ ] ,
144+ } ;
145+ conn. send ( msg) . await . expect ( "Send b" ) ;
146+ }
147+
148+ // Test to recieve a message
149+ #[ tokio:: test]
150+ #[ ignore]
151+ async fn test_subscribe ( ) {
152+ let sub_msg = crate :: client:: subscribe ( "/test/a" , "tjo" ) ;
153+ let mut conn = crate :: client:: connect (
154+ "localhost:61613" ,
155+ "/" ,
156+ //None,None
157+ Some ( "artemis" . to_string ( ) ) ,
158+ Some ( "artemis" . to_string ( ) ) ,
159+ )
160+ . await
161+ . expect ( "Default connection to localhost" ) ;
162+ conn. send ( sub_msg) . await . expect ( "Send subscribe" ) ;
163+ let ( _sink, stream) = conn. split ( ) ;
164+
165+ let mut cnt = 0 ;
166+ let _ = stream
167+ . try_for_each ( |item| {
168+ println ! ( "==== {cnt}" ) ;
169+ cnt += 1 ;
170+ if let FromServer :: Message { body, .. } = item. content {
171+ println ! (
172+ "Message received: {:?}" ,
173+ String :: from_utf8_lossy( & body. unwrap( ) )
174+ ) ;
175+ } else {
176+ println ! ( "{:?}" , item) ;
177+ }
178+ ok ( ( ) )
179+ } )
180+ . await ;
181+ }
182+
183+ // Test to send and recieve message
184+ #[ tokio:: test]
185+ #[ ignore]
186+ async fn test_send_subscribe ( ) {
187+ let conn = client:: connect (
188+ "127.0.0.1:61613" ,
189+ "/" . to_string ( ) ,
190+ "artemis" . to_string ( ) . into ( ) ,
191+ "artemis" . to_string ( ) . into ( ) ,
192+ )
193+ . await
194+ . expect ( "Connect" ) ;
195+
196+ tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
197+
198+ let ( mut sink, stream) = conn. split ( ) ;
199+
200+ let fut1 = async move {
201+ sink. send ( client:: subscribe ( "rusty" , "myid" ) ) . await ?;
202+ println ! ( "Subscribe sent" ) ;
203+
204+ tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
205+
206+ sink. send (
207+ ToServer :: Send {
208+ destination : "rusty" . into ( ) ,
209+ transaction : None ,
210+ headers : None ,
211+ body : Some ( b"Hello there rustaceans!" . to_vec ( ) ) ,
212+ }
213+ . into ( ) ,
214+ )
215+ . await ?;
216+ println ! ( "Message sent" ) ;
217+
218+ tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
219+
220+ sink. send ( ToServer :: Unsubscribe { id : "myid" . into ( ) } . into ( ) )
221+ . await ?;
222+ println ! ( "Unsubscribe sent" ) ;
223+
224+ tokio:: time:: sleep ( Duration :: from_millis ( 200 ) ) . await ;
225+
226+ tokio:: time:: sleep ( Duration :: from_secs ( 1 ) ) . await ;
227+ sink. send ( ToServer :: Disconnect { receipt : None } . into ( ) )
228+ . await ?;
229+ println ! ( "Disconnect sent" ) ;
230+
231+ Ok ( ( ) )
232+ } ;
233+
234+ // Listen from the main thread. Once the Disconnect message is sent from
235+ // the sender thread, the server will disconnect the client and the future
236+ // will resolve, ending the program
237+ let fut2 = stream. try_for_each ( |item| {
238+ if let FromServer :: Message { body, .. } = item. content {
239+ println ! (
240+ "Message received: {:?}" ,
241+ String :: from_utf8_lossy( & body. unwrap( ) )
242+ ) ;
243+ } else {
244+ // println!("{:?}", item);
245+ }
246+ ok ( ( ) )
247+ } ) ;
248+
249+ futures:: future:: select ( Box :: pin ( fut1) , Box :: pin ( fut2) )
250+ . await
251+ . factor_first ( )
252+ . 0
253+ . expect ( "Select" ) ;
254+ }
255+ }
0 commit comments