@@ -336,6 +336,74 @@ impl ConnectionBuilder {
336336 }
337337}
338338
339+ cfg_sync ! {
340+ trait WriteQuerySync {
341+ fn write_sync( & self , b: & mut impl std:: io:: Write ) -> IoResult <( ) >;
342+ }
343+
344+ impl WriteQuerySync for Query {
345+ fn write_sync( & self , stream: & mut impl std:: io:: Write ) -> IoResult <( ) > {
346+ // Write the metaframe
347+ stream. write_all( b"*1\n " ) ?;
348+ // Add the dataframe
349+ let number_of_items_in_datagroup = self . len( ) . to_string( ) . into_bytes( ) ;
350+ stream. write_all( & [ b'~' ] ) ?;
351+ stream. write_all( & number_of_items_in_datagroup) ?;
352+ stream. write_all( & [ b'\n' ] ) ?;
353+ stream. write_all( self . get_holding_buffer( ) ) ?;
354+ stream. flush( ) ?;
355+ Ok ( ( ) )
356+ }
357+ }
358+
359+ impl WriteQuerySync for Pipeline {
360+ fn write_sync( & self , stream: & mut impl std:: io:: Write ) -> IoResult <( ) > {
361+ let len = self . len. to_string( ) . into_bytes( ) ;
362+ stream. write_all( b"*" ) ?;
363+ stream. write_all( & len) ?;
364+ stream. write_all( b"\n " ) ?;
365+ stream. write_all( & self . chain)
366+ }
367+ }
368+ }
369+
370+ cfg_async ! {
371+ use core:: pin:: Pin ;
372+ use core:: future:: Future ;
373+ use tokio:: io:: AsyncWrite ;
374+ type FutureRet <' s> = Pin <Box <dyn Future <Output = IoResult <( ) >> + Send + Sync + ' s>>;
375+ trait WriteQueryAsync <T : AsyncWrite + Unpin + Send + Sync >: Unpin + Sync + Send {
376+ fn write_async<' s>( & ' s self , b: & ' s mut T ) -> FutureRet <' s>;
377+ }
378+ impl <T : AsyncWrite + Unpin + Send + Sync > WriteQueryAsync <T > for Query {
379+ fn write_async<' s>( & ' s self , stream: & ' s mut T ) -> FutureRet {
380+ Box :: pin( async move {
381+ // Write the metaframe
382+ stream. write_all( b"*1\n " ) . await ?;
383+ // Add the dataframe
384+ let number_of_items_in_datagroup = self . len( ) . to_string( ) . into_bytes( ) ;
385+ stream. write_all( & [ b'~' ] ) . await ?;
386+ stream. write_all( & number_of_items_in_datagroup) . await ?;
387+ stream. write_all( & [ b'\n' ] ) . await ?;
388+ stream. write_all( self . get_holding_buffer( ) ) . await ?;
389+ stream. flush( ) . await ?;
390+ Ok ( ( ) )
391+ } )
392+ }
393+ }
394+ impl <T : AsyncWrite + Unpin + Send + Sync > WriteQueryAsync <T > for Pipeline {
395+ fn write_async<' s>( & ' s self , stream: & ' s mut T ) -> FutureRet {
396+ Box :: pin( async move {
397+ let len = self . len. to_string( ) . into_bytes( ) ;
398+ stream. write_all( b"*" ) . await ?;
399+ stream. write_all( & len) . await ?;
400+ stream. write_all( b"\n " ) . await ?;
401+ stream. write_all( & self . chain) . await
402+ } )
403+ }
404+ }
405+ }
406+
339407#[ macro_export]
340408/// A macro that can be used to easily create queries with _almost_ variadic properties.
341409/// Where you'd normally create queries like this:
@@ -472,42 +540,14 @@ impl Query {
472540 fn get_holding_buffer ( & self ) -> & [ u8 ] {
473541 & self . data
474542 }
475- cfg_async ! (
476- /// Write a query to a given stream
477- async fn write_query_to<T >( & self , stream: & mut T ) -> IoResult <( ) >
478- where
479- T : tokio:: io:: AsyncWrite + Unpin ,
480- {
481- // Write the metaframe
482- stream. write_all( b"*1\n " ) . await ?;
483- // Add the dataframe
484- let number_of_items_in_datagroup = self . len( ) . to_string( ) . into_bytes( ) ;
485- stream. write_all( & [ b'~' ] ) . await ?;
486- stream. write_all( & number_of_items_in_datagroup) . await ?;
487- stream. write_all( & [ b'\n' ] ) . await ?;
488- stream. write_all( self . get_holding_buffer( ) ) . await ?;
489- stream. flush( ) . await ?;
490- Ok ( ( ) )
491- }
492- ) ;
493- cfg_sync ! (
494- /// Write a query to a given stream
495- fn write_query_to_sync<T >( & self , stream: & mut T ) -> IoResult <( ) >
496- where
497- T : std:: io:: Write ,
498- {
499- // Write the metaframe
500- stream. write_all( b"*1\n " ) ?;
501- // Add the dataframe
502- let number_of_items_in_datagroup = self . len( ) . to_string( ) . into_bytes( ) ;
503- stream. write_all( & [ b'~' ] ) ?;
504- stream. write_all( & number_of_items_in_datagroup) ?;
505- stream. write_all( & [ b'\n' ] ) ?;
506- stream. write_all( self . get_holding_buffer( ) ) ?;
507- stream. flush( ) ?;
508- Ok ( ( ) )
509- }
510- ) ;
543+ fn write_query_to_writable ( & self , buffer : & mut Vec < u8 > ) {
544+ // Add the dataframe element
545+ let number_of_items_in_datagroup = self . len ( ) . to_string ( ) . into_bytes ( ) ;
546+ buffer. extend ( [ b'~' ] ) ;
547+ buffer. extend ( & number_of_items_in_datagroup) ;
548+ buffer. extend ( [ b'\n' ] ) ;
549+ buffer. extend ( self . get_holding_buffer ( ) ) ;
550+ }
511551 cfg_dbg ! (
512552 /// Get the raw bytes of a query
513553 ///
@@ -564,3 +604,36 @@ cfg_dbg!(
564604 assert_eq!( ma_query_len, q_len) ;
565605 }
566606) ;
607+
608+ /// # Pipeline
609+ ///
610+ /// A pipeline is a way of queing up multiple queries, sending them to the server at once instead of sending them individually, avoiding
611+ /// round-trip-times while also simplifying usage in several places. Responses are returned in the order they are sent
612+ pub struct Pipeline {
613+ len : usize ,
614+ chain : Vec < u8 > ,
615+ }
616+
617+ impl Pipeline {
618+ /// Initializes a new empty pipeline
619+ pub fn new ( ) -> Self {
620+ Self {
621+ len : 0usize ,
622+ chain : Vec :: new ( ) ,
623+ }
624+ }
625+ /// Append a query (builder pattern)
626+ pub fn add ( mut self , query : Query ) -> Self {
627+ self . len += 1 ;
628+ query. write_query_to_writable ( & mut self . chain ) ;
629+ self
630+ }
631+ /// Append a query by taking reference
632+ pub fn push ( & mut self , query : Query ) {
633+ self . len += 1 ;
634+ query. write_query_to_writable ( & mut self . chain ) ;
635+ }
636+ pub fn len ( & self ) -> usize {
637+ self . len
638+ }
639+ }
0 commit comments