@@ -75,12 +75,12 @@ impl FlowControl {
7575 self . window_size > self . available
7676 }
7777
78- pub fn claim_capacity ( & mut self , capacity : WindowSize ) {
79- self . available -= capacity;
78+ pub fn claim_capacity ( & mut self , capacity : WindowSize ) -> Result < ( ) , Reason > {
79+ self . available . decrease_by ( capacity)
8080 }
8181
82- pub fn assign_capacity ( & mut self , capacity : WindowSize ) {
83- self . available += capacity;
82+ pub fn assign_capacity ( & mut self , capacity : WindowSize ) -> Result < ( ) , Reason > {
83+ self . available . increase_by ( capacity)
8484 }
8585
8686 /// If a WINDOW_UPDATE frame should be sent, returns a positive number
@@ -136,36 +136,38 @@ impl FlowControl {
136136 ///
137137 /// This is called after receiving a SETTINGS frame with a lower
138138 /// INITIAL_WINDOW_SIZE value.
139- pub fn dec_send_window ( & mut self , sz : WindowSize ) {
139+ pub fn dec_send_window ( & mut self , sz : WindowSize ) -> Result < ( ) , Reason > {
140140 tracing:: trace!(
141141 "dec_window; sz={}; window={}, available={}" ,
142142 sz,
143143 self . window_size,
144144 self . available
145145 ) ;
146- // This should not be able to overflow `window_size` from the bottom.
147- self . window_size -= sz;
146+ // ~~This should not be able to overflow `window_size` from the bottom.~~ wrong. it can.
147+ self . window_size . decrease_by ( sz) ?;
148+ Ok ( ( ) )
148149 }
149150
150151 /// Decrement the recv-side window size.
151152 ///
152153 /// This is called after receiving a SETTINGS ACK frame with a lower
153154 /// INITIAL_WINDOW_SIZE value.
154- pub fn dec_recv_window ( & mut self , sz : WindowSize ) {
155+ pub fn dec_recv_window ( & mut self , sz : WindowSize ) -> Result < ( ) , Reason > {
155156 tracing:: trace!(
156157 "dec_recv_window; sz={}; window={}, available={}" ,
157158 sz,
158159 self . window_size,
159160 self . available
160161 ) ;
161162 // This should not be able to overflow `window_size` from the bottom.
162- self . window_size -= sz;
163- self . available -= sz;
163+ self . window_size . decrease_by ( sz) ?;
164+ self . available . decrease_by ( sz) ?;
165+ Ok ( ( ) )
164166 }
165167
166168 /// Decrements the window reflecting data has actually been sent. The caller
167169 /// must ensure that the window has capacity.
168- pub fn send_data ( & mut self , sz : WindowSize ) {
170+ pub fn send_data ( & mut self , sz : WindowSize ) -> Result < ( ) , Reason > {
169171 tracing:: trace!(
170172 "send_data; sz={}; window={}; available={}" ,
171173 sz,
@@ -176,12 +178,13 @@ impl FlowControl {
176178 // If send size is zero it's meaningless to update flow control window
177179 if sz > 0 {
178180 // Ensure that the argument is correct
179- assert ! ( self . window_size >= sz as usize ) ;
181+ assert ! ( self . window_size. 0 >= sz as i32 ) ;
180182
181183 // Update values
182- self . window_size -= sz ;
183- self . available -= sz ;
184+ self . window_size . decrease_by ( sz ) ? ;
185+ self . available . decrease_by ( sz ) ? ;
184186 }
187+ Ok ( ( ) )
185188 }
186189}
187190
@@ -208,6 +211,29 @@ impl Window {
208211 assert ! ( self . 0 >= 0 , "negative Window" ) ;
209212 self . 0 as WindowSize
210213 }
214+
215+ pub fn decrease_by ( & mut self , other : WindowSize ) -> Result < ( ) , Reason > {
216+ if let Some ( v) = self . 0 . checked_sub ( other as i32 ) {
217+ self . 0 = v;
218+ Ok ( ( ) )
219+ } else {
220+ Err ( Reason :: FLOW_CONTROL_ERROR )
221+ }
222+ }
223+
224+ pub fn increase_by ( & mut self , other : WindowSize ) -> Result < ( ) , Reason > {
225+ let other = self . add ( other) ?;
226+ self . 0 = other. 0 ;
227+ Ok ( ( ) )
228+ }
229+
230+ pub fn add ( & self , other : WindowSize ) -> Result < Self , Reason > {
231+ if let Some ( v) = self . 0 . checked_add ( other as i32 ) {
232+ Ok ( Self ( v) )
233+ } else {
234+ Err ( Reason :: FLOW_CONTROL_ERROR )
235+ }
236+ }
211237}
212238
213239impl PartialEq < usize > for Window {
@@ -230,25 +256,6 @@ impl PartialOrd<usize> for Window {
230256 }
231257}
232258
233- impl :: std:: ops:: SubAssign < WindowSize > for Window {
234- fn sub_assign ( & mut self , other : WindowSize ) {
235- self . 0 -= other as i32 ;
236- }
237- }
238-
239- impl :: std:: ops:: Add < WindowSize > for Window {
240- type Output = Self ;
241- fn add ( self , other : WindowSize ) -> Self :: Output {
242- Window ( self . 0 + other as i32 )
243- }
244- }
245-
246- impl :: std:: ops:: AddAssign < WindowSize > for Window {
247- fn add_assign ( & mut self , other : WindowSize ) {
248- self . 0 += other as i32 ;
249- }
250- }
251-
252259impl fmt:: Display for Window {
253260 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
254261 fmt:: Display :: fmt ( & self . 0 , f)
0 commit comments