@@ -5,7 +5,11 @@ use cfb8::{
55 stream_cipher:: { NewStreamCipher , StreamCipher } ,
66 Cfb8 ,
77} ;
8- use std:: io:: Cursor ;
8+ use flate2:: {
9+ bufread:: { ZlibDecoder , ZlibEncoder } ,
10+ Compression ,
11+ } ;
12+ use std:: io:: { Cursor , Read } ;
913
1014type AesCfb8 = Cfb8 < Aes128 > ;
1115pub type CompressionThreshold = usize ;
@@ -24,8 +28,10 @@ pub struct MinecraftCodec {
2428
2529 /// A buffer of received bytes.
2630 received_buf : BytesMut ,
27- /// Auxilary buffer for use with compression .
31+ /// Auxilary buffer.
2832 staging_buf : Vec < u8 > ,
33+ /// Another auxilary buffer.
34+ compression_target : Vec < u8 > ,
2935}
3036
3137impl MinecraftCodec {
@@ -56,6 +62,7 @@ impl MinecraftCodec {
5662 compression : self . compression ,
5763 received_buf : BytesMut :: new ( ) ,
5864 staging_buf : Vec :: new ( ) ,
65+ compression_target : Vec :: new ( ) ,
5966 }
6067 }
6168
@@ -76,8 +83,38 @@ impl MinecraftCodec {
7683 self . staging_buf . clear ( ) ;
7784 }
7885
79- fn encode_compressed ( & mut self , _output : & mut Vec < u8 > , _threshold : CompressionThreshold ) {
80- todo ! ( )
86+ fn encode_compressed ( & mut self , output : & mut Vec < u8 > , threshold : CompressionThreshold ) {
87+ let ( data_length, data) = if self . staging_buf . len ( ) >= threshold {
88+ self . data_compressed ( )
89+ } else {
90+ self . data_uncompressed ( )
91+ } ;
92+
93+ const MAX_VAR_INT_LENGTH : usize = 5 ;
94+ let mut buf = [ 0u8 ; MAX_VAR_INT_LENGTH ] ;
95+ let mut data_length_bytes = Cursor :: new ( & mut buf[ ..] ) ;
96+ VarInt ( data_length as i32 )
97+ . write_to ( & mut data_length_bytes)
98+ . unwrap ( ) ;
99+
100+ let packet_length = data_length_bytes. position ( ) as usize + data. len ( ) ;
101+ VarInt ( packet_length as i32 ) . write ( output, ProtocolVersion :: V1_16_2 ) ;
102+ VarInt ( data_length as i32 ) . write ( output, ProtocolVersion :: V1_16_2 ) ;
103+ output. extend_from_slice ( data) ;
104+
105+ self . compression_target . clear ( ) ;
106+ }
107+
108+ fn data_compressed ( & mut self ) -> ( usize , & [ u8 ] ) {
109+ let mut encoder = ZlibEncoder :: new ( self . staging_buf . as_slice ( ) , Compression :: default ( ) ) ;
110+ encoder
111+ . read_to_end ( & mut self . compression_target )
112+ . expect ( "compression failed" ) ;
113+ ( self . staging_buf . len ( ) , self . compression_target . as_slice ( ) )
114+ }
115+
116+ fn data_uncompressed ( & mut self ) -> ( usize , & [ u8 ] ) {
117+ ( 0 , self . staging_buf . as_slice ( ) )
81118 }
82119
83120 fn encode_uncompressed ( & mut self , output : & mut Vec < u8 > ) {
@@ -114,11 +151,23 @@ impl MinecraftCodec {
114151 & self . received_buf
115152 [ length_field_length..length_field_length + length. 0 as usize ] ,
116153 ) ;
154+
155+ if self . compression . is_some ( ) {
156+ let data_length = VarInt :: read ( & mut cursor, ProtocolVersion :: V1_16_2 ) ?;
157+ if data_length. 0 != 0 {
158+ let mut decoder =
159+ ZlibDecoder :: new ( & cursor. get_ref ( ) [ cursor. position ( ) as usize ..] ) ;
160+ decoder. read_to_end ( & mut self . compression_target ) ?;
161+ cursor = Cursor :: new ( & self . compression_target ) ;
162+ }
163+ }
164+
117165 let packet = T :: read ( & mut cursor, ProtocolVersion :: V1_16_2 ) ?;
118166
119167 let bytes_read = cursor. position ( ) as usize + length_field_length;
120168 self . received_buf = self . received_buf . split_off ( bytes_read) ;
121169
170+ self . compression_target . clear ( ) ;
122171 Some ( packet)
123172 } else {
124173 None
0 commit comments