14
14
//!
15
15
//! * Should probably have something like this for strings.
16
16
//! * Should they implement Closable? Would take extra state.
17
-
17
+ use cmp :: max ;
18
18
use cmp:: min;
19
19
use prelude:: * ;
20
20
use super :: * ;
@@ -64,15 +64,19 @@ impl Writer for MemWriter {
64
64
}
65
65
}
66
66
67
+ // FIXME(#10432)
67
68
impl Seek for MemWriter {
68
69
fn tell ( & self ) -> u64 { self . pos as u64 }
69
70
70
71
fn seek ( & mut self , pos : i64 , style : SeekStyle ) {
71
- match style {
72
- SeekSet => { self . pos = pos as uint ; }
73
- SeekEnd => { self . pos = self . buf . len ( ) + pos as uint ; }
74
- SeekCur => { self . pos += pos as uint ; }
75
- }
72
+ // compute offset as signed and clamp to prevent overflow
73
+ let offset = match style {
74
+ SeekSet => { 0 }
75
+ SeekEnd => { self . buf . len ( ) }
76
+ SeekCur => { self . pos }
77
+ } as i64 ;
78
+
79
+ self . pos = max ( 0 , offset+pos) as uint ;
76
80
}
77
81
}
78
82
@@ -146,6 +150,9 @@ impl Decorator<~[u8]> for MemReader {
146
150
147
151
148
152
/// Writes to a fixed-size byte slice
153
+ ///
154
+ /// If a write will not fit in the buffer, it raises the `io_error`
155
+ /// condition and does not write any data.
149
156
pub struct BufWriter < ' self > {
150
157
priv buf: & ' self mut [ u8 ] ,
151
158
priv pos: uint
@@ -161,15 +168,38 @@ impl<'self> BufWriter<'self> {
161
168
}
162
169
163
170
impl < ' self > Writer for BufWriter < ' self > {
164
- fn write ( & mut self , _buf : & [ u8 ] ) { fail ! ( ) }
171
+ fn write ( & mut self , buf : & [ u8 ] ) {
172
+ // raises a condition if the entire write does not fit in the buffer
173
+ let max_size = self . buf . len ( ) ;
174
+ if self . pos >= max_size || ( self . pos + buf. len ( ) ) > max_size {
175
+ io_error:: cond. raise ( IoError {
176
+ kind : OtherIoError ,
177
+ desc : "Trying to write past end of buffer" ,
178
+ detail : None
179
+ } ) ;
180
+ return ;
181
+ }
165
182
166
- fn flush ( & mut self ) { fail ! ( ) }
183
+ vec:: bytes:: copy_memory ( self . buf . mut_slice_from ( self . pos ) ,
184
+ buf, buf. len ( ) ) ;
185
+ self . pos += buf. len ( ) ;
186
+ }
167
187
}
168
188
189
+ // FIXME(#10432)
169
190
impl < ' self > Seek for BufWriter < ' self > {
170
- fn tell ( & self ) -> u64 { fail ! ( ) }
191
+ fn tell ( & self ) -> u64 { self . pos as u64 }
171
192
172
- fn seek ( & mut self , _pos : i64 , _style : SeekStyle ) { fail ! ( ) }
193
+ fn seek ( & mut self , pos : i64 , style : SeekStyle ) {
194
+ // compute offset as signed and clamp to prevent overflow
195
+ let offset = match style {
196
+ SeekSet => { 0 }
197
+ SeekEnd => { self . buf . len ( ) }
198
+ SeekCur => { self . pos }
199
+ } as i64 ;
200
+
201
+ self . pos = max ( 0 , offset+pos) as uint ;
202
+ }
173
203
}
174
204
175
205
@@ -257,6 +287,65 @@ mod test {
257
287
assert_eq ! ( * writer. inner_ref( ) , ~[ 3 , 4 , 2 , 0 , 1 , 5 , 6 , 1 , 2 , 0 , 1 ] ) ;
258
288
}
259
289
290
+ #[ test]
291
+ fn test_buf_writer ( ) {
292
+ let mut buf = [ 0 as u8 , ..8 ] ;
293
+ {
294
+ let mut writer = BufWriter :: new ( buf) ;
295
+ assert_eq ! ( writer. tell( ) , 0 ) ;
296
+ writer. write ( [ 0 ] ) ;
297
+ assert_eq ! ( writer. tell( ) , 1 ) ;
298
+ writer. write ( [ 1 , 2 , 3 ] ) ;
299
+ writer. write ( [ 4 , 5 , 6 , 7 ] ) ;
300
+ assert_eq ! ( writer. tell( ) , 8 ) ;
301
+ }
302
+ assert_eq ! ( buf, [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ) ;
303
+ }
304
+
305
+ #[ test]
306
+ fn test_buf_writer_seek ( ) {
307
+ let mut buf = [ 0 as u8 , ..8 ] ;
308
+ {
309
+ let mut writer = BufWriter :: new ( buf) ;
310
+ assert_eq ! ( writer. tell( ) , 0 ) ;
311
+ writer. write ( [ 1 ] ) ;
312
+ assert_eq ! ( writer. tell( ) , 1 ) ;
313
+
314
+ writer. seek ( 2 , SeekSet ) ;
315
+ assert_eq ! ( writer. tell( ) , 2 ) ;
316
+ writer. write ( [ 2 ] ) ;
317
+ assert_eq ! ( writer. tell( ) , 3 ) ;
318
+
319
+ writer. seek ( -2 , SeekCur ) ;
320
+ assert_eq ! ( writer. tell( ) , 1 ) ;
321
+ writer. write ( [ 3 ] ) ;
322
+ assert_eq ! ( writer. tell( ) , 2 ) ;
323
+
324
+ writer. seek ( -1 , SeekEnd ) ;
325
+ assert_eq ! ( writer. tell( ) , 7 ) ;
326
+ writer. write ( [ 4 ] ) ;
327
+ assert_eq ! ( writer. tell( ) , 8 ) ;
328
+
329
+ }
330
+ assert_eq ! ( buf, [ 1 , 3 , 2 , 0 , 0 , 0 , 0 , 4 ] ) ;
331
+ }
332
+
333
+ #[ test]
334
+ fn test_buf_writer_error ( ) {
335
+ let mut buf = [ 0 as u8 , ..2 ] ;
336
+ let mut writer = BufWriter :: new ( buf) ;
337
+ writer. write ( [ 0 ] ) ;
338
+
339
+ let mut called = false ;
340
+ do io_error:: cond. trap ( |err| {
341
+ assert_eq ! ( err. kind, OtherIoError ) ;
342
+ called = true ;
343
+ } ) . inside {
344
+ writer. write ( [ 0 , 0 ] ) ;
345
+ }
346
+ assert ! ( called) ;
347
+ }
348
+
260
349
#[ test]
261
350
fn test_mem_reader ( ) {
262
351
let mut reader = MemReader :: new ( ~[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ) ;
0 commit comments