]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/extensions.rs
auto merge of #11598 : alexcrichton/rust/io-export, r=brson
[rust.git] / src / libstd / io / extensions.rs
1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Utility mixins that apply to all Readers and Writers
12
13 // XXX: Not sure how this should be structured
14 // XXX: Iteration should probably be considered separately
15
16 use container::Container;
17 use iter::Iterator;
18 use option::Option;
19 use io::Reader;
20 use vec::{OwnedVector, ImmutableVector};
21
22 /// An iterator that reads a single byte on each iteration,
23 /// until `.read_byte()` returns `None`.
24 ///
25 /// # Notes about the Iteration Protocol
26 ///
27 /// The `ByteIterator` may yield `None` and thus terminate
28 /// an iteration, but continue to yield elements if iteration
29 /// is attempted again.
30 ///
31 /// # Failure
32 ///
33 /// Raises the same conditions as the `read` method, for
34 /// each call to its `.next()` method.
35 /// Yields `None` if the condition is handled.
36 pub struct ByteIterator<'r, T> {
37     priv reader: &'r mut T,
38 }
39
40 impl<'r, R: Reader> ByteIterator<'r, R> {
41     pub fn new(r: &'r mut R) -> ByteIterator<'r, R> {
42         ByteIterator { reader: r }
43     }
44 }
45
46 impl<'r, R: Reader> Iterator<u8> for ByteIterator<'r, R> {
47     #[inline]
48     fn next(&mut self) -> Option<u8> {
49         self.reader.read_byte()
50     }
51 }
52
53 pub fn u64_to_le_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
54     assert!(size <= 8u);
55     match size {
56       1u => f(&[n as u8]),
57       2u => f(&[n as u8,
58               (n >> 8) as u8]),
59       4u => f(&[n as u8,
60               (n >> 8) as u8,
61               (n >> 16) as u8,
62               (n >> 24) as u8]),
63       8u => f(&[n as u8,
64               (n >> 8) as u8,
65               (n >> 16) as u8,
66               (n >> 24) as u8,
67               (n >> 32) as u8,
68               (n >> 40) as u8,
69               (n >> 48) as u8,
70               (n >> 56) as u8]),
71       _ => {
72
73         let mut bytes: ~[u8] = ~[];
74         let mut i = size;
75         let mut n = n;
76         while i > 0u {
77             bytes.push((n & 255_u64) as u8);
78             n >>= 8_u64;
79             i -= 1u;
80         }
81         f(bytes)
82       }
83     }
84 }
85
86 pub fn u64_to_be_bytes<T>(n: u64, size: uint, f: |v: &[u8]| -> T) -> T {
87     assert!(size <= 8u);
88     match size {
89       1u => f(&[n as u8]),
90       2u => f(&[(n >> 8) as u8,
91               n as u8]),
92       4u => f(&[(n >> 24) as u8,
93               (n >> 16) as u8,
94               (n >> 8) as u8,
95               n as u8]),
96       8u => f(&[(n >> 56) as u8,
97               (n >> 48) as u8,
98               (n >> 40) as u8,
99               (n >> 32) as u8,
100               (n >> 24) as u8,
101               (n >> 16) as u8,
102               (n >> 8) as u8,
103               n as u8]),
104       _ => {
105         let mut bytes: ~[u8] = ~[];
106         let mut i = size;
107         while i > 0u {
108             let shift = ((i - 1u) * 8u) as u64;
109             bytes.push((n >> shift) as u8);
110             i -= 1u;
111         }
112         f(bytes)
113       }
114     }
115 }
116
117 pub fn u64_from_be_bytes(data: &[u8],
118                          start: uint,
119                          size: uint)
120                       -> u64 {
121     use ptr::{copy_nonoverlapping_memory, offset, mut_offset};
122     use unstable::intrinsics::from_be64;
123     use vec::MutableVector;
124
125     assert!(size <= 8u);
126
127     if data.len() - start < size {
128         fail!("index out of bounds");
129     }
130
131     let mut buf = [0u8, ..8];
132     unsafe {
133         let ptr = offset(data.as_ptr(), start as int);
134         let out = buf.as_mut_ptr();
135         copy_nonoverlapping_memory(mut_offset(out, (8 - size) as int), ptr, size);
136         from_be64(*(out as *i64)) as u64
137     }
138 }
139
140 #[cfg(test)]
141 mod test {
142     use unstable::finally::Finally;
143     use prelude::*;
144     use io::{MemReader, MemWriter};
145     use io::{io_error, placeholder_error};
146
147     struct InitialZeroByteReader {
148         count: int,
149     }
150
151     impl Reader for InitialZeroByteReader {
152         fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
153             if self.count == 0 {
154                 self.count = 1;
155                 Some(0)
156             } else {
157                 buf[0] = 10;
158                 Some(1)
159             }
160         }
161     }
162
163     struct EofReader;
164
165     impl Reader for EofReader {
166         fn read(&mut self, _: &mut [u8]) -> Option<uint> {
167             None
168         }
169     }
170
171     struct ErroringReader;
172
173     impl Reader for ErroringReader {
174         fn read(&mut self, _: &mut [u8]) -> Option<uint> {
175             io_error::cond.raise(placeholder_error());
176             None
177         }
178     }
179
180     struct PartialReader {
181         count: int,
182     }
183
184     impl Reader for PartialReader {
185         fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
186             if self.count == 0 {
187                 self.count = 1;
188                 buf[0] = 10;
189                 buf[1] = 11;
190                 Some(2)
191             } else {
192                 buf[0] = 12;
193                 buf[1] = 13;
194                 Some(2)
195             }
196         }
197     }
198
199     struct ErroringLaterReader {
200         count: int,
201     }
202
203     impl Reader for ErroringLaterReader {
204         fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
205             if self.count == 0 {
206                 self.count = 1;
207                 buf[0] = 10;
208                 Some(1)
209             } else {
210                 io_error::cond.raise(placeholder_error());
211                 None
212             }
213         }
214     }
215
216     struct ThreeChunkReader {
217         count: int,
218     }
219
220     impl Reader for ThreeChunkReader {
221         fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
222             if self.count == 0 {
223                 self.count = 1;
224                 buf[0] = 10;
225                 buf[1] = 11;
226                 Some(2)
227             } else if self.count == 1 {
228                 self.count = 2;
229                 buf[0] = 12;
230                 buf[1] = 13;
231                 Some(2)
232             } else {
233                 None
234             }
235         }
236     }
237
238     #[test]
239     fn read_byte() {
240         let mut reader = MemReader::new(~[10]);
241         let byte = reader.read_byte();
242         assert!(byte == Some(10));
243     }
244
245     #[test]
246     fn read_byte_0_bytes() {
247         let mut reader = InitialZeroByteReader {
248             count: 0,
249         };
250         let byte = reader.read_byte();
251         assert!(byte == Some(10));
252     }
253
254     #[test]
255     fn read_byte_eof() {
256         let mut reader = EofReader;
257         let byte = reader.read_byte();
258         assert!(byte == None);
259     }
260
261     #[test]
262     fn read_byte_error() {
263         let mut reader = ErroringReader;
264         io_error::cond.trap(|_| {
265         }).inside(|| {
266             let byte = reader.read_byte();
267             assert!(byte == None);
268         });
269     }
270
271     #[test]
272     fn bytes_0_bytes() {
273         let mut reader = InitialZeroByteReader {
274             count: 0,
275         };
276         let byte = reader.bytes().next();
277         assert!(byte == Some(10));
278     }
279
280     #[test]
281     fn bytes_eof() {
282         let mut reader = EofReader;
283         let byte = reader.bytes().next();
284         assert!(byte == None);
285     }
286
287     #[test]
288     fn bytes_error() {
289         let mut reader = ErroringReader;
290         let mut it = reader.bytes();
291         io_error::cond.trap(|_| ()).inside(|| {
292             let byte = it.next();
293             assert!(byte == None);
294         })
295     }
296
297     #[test]
298     fn read_bytes() {
299         let mut reader = MemReader::new(~[10, 11, 12, 13]);
300         let bytes = reader.read_bytes(4);
301         assert!(bytes == ~[10, 11, 12, 13]);
302     }
303
304     #[test]
305     fn read_bytes_partial() {
306         let mut reader = PartialReader {
307             count: 0,
308         };
309         let bytes = reader.read_bytes(4);
310         assert!(bytes == ~[10, 11, 12, 13]);
311     }
312
313     #[test]
314     fn read_bytes_eof() {
315         let mut reader = MemReader::new(~[10, 11]);
316         io_error::cond.trap(|_| {
317         }).inside(|| {
318             assert!(reader.read_bytes(4) == ~[10, 11]);
319         })
320     }
321
322     #[test]
323     fn push_bytes() {
324         let mut reader = MemReader::new(~[10, 11, 12, 13]);
325         let mut buf = ~[8, 9];
326         reader.push_bytes(&mut buf, 4);
327         assert!(buf == ~[8, 9, 10, 11, 12, 13]);
328     }
329
330     #[test]
331     fn push_bytes_partial() {
332         let mut reader = PartialReader {
333             count: 0,
334         };
335         let mut buf = ~[8, 9];
336         reader.push_bytes(&mut buf, 4);
337         assert!(buf == ~[8, 9, 10, 11, 12, 13]);
338     }
339
340     #[test]
341     fn push_bytes_eof() {
342         let mut reader = MemReader::new(~[10, 11]);
343         let mut buf = ~[8, 9];
344         io_error::cond.trap(|_| {
345         }).inside(|| {
346             reader.push_bytes(&mut buf, 4);
347             assert!(buf == ~[8, 9, 10, 11]);
348         })
349     }
350
351     #[test]
352     fn push_bytes_error() {
353         let mut reader = ErroringLaterReader {
354             count: 0,
355         };
356         let mut buf = ~[8, 9];
357         io_error::cond.trap(|_| { } ).inside(|| {
358             reader.push_bytes(&mut buf, 4);
359         });
360         assert!(buf == ~[8, 9, 10]);
361     }
362
363     #[test]
364     #[should_fail]
365     #[ignore] // borrow issues with RefCell
366     fn push_bytes_fail_reset_len() {
367         // push_bytes unsafely sets the vector length. This is testing that
368         // upon failure the length is reset correctly.
369         let reader = ErroringLaterReader {
370             count: 0,
371         };
372         // FIXME (#7049): Figure out some other way to do this.
373         //let buf = RefCell::new(~[8, 9]);
374         (|| {
375             //reader.push_bytes(buf.borrow_mut().get(), 4);
376         }).finally(|| {
377             // NB: Using rtassert here to trigger abort on failure since this is a should_fail test
378             // FIXME: #7049 This fails because buf is still borrowed
379             //rtassert!(buf.borrow().get() == ~[8, 9, 10]);
380         })
381     }
382
383     #[test]
384     fn read_to_end() {
385         let mut reader = ThreeChunkReader {
386             count: 0,
387         };
388         let buf = reader.read_to_end();
389         assert!(buf == ~[10, 11, 12, 13]);
390     }
391
392     #[test]
393     #[should_fail]
394     fn read_to_end_error() {
395         let mut reader = ThreeChunkReader {
396             count: 0,
397         };
398         let buf = reader.read_to_end();
399         assert!(buf == ~[10, 11]);
400     }
401
402     #[test]
403     fn test_read_write_le_mem() {
404         let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
405
406         let mut writer = MemWriter::new();
407         for i in uints.iter() {
408             writer.write_le_u64(*i);
409         }
410
411         let mut reader = MemReader::new(writer.unwrap());
412         for i in uints.iter() {
413             assert!(reader.read_le_u64() == *i);
414         }
415     }
416
417
418     #[test]
419     fn test_read_write_be() {
420         let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
421
422         let mut writer = MemWriter::new();
423         for i in uints.iter() {
424             writer.write_be_u64(*i);
425         }
426
427         let mut reader = MemReader::new(writer.unwrap());
428         for i in uints.iter() {
429             assert!(reader.read_be_u64() == *i);
430         }
431     }
432
433     #[test]
434     fn test_read_be_int_n() {
435         let ints = [::i32::min_value, -123456, -42, -5, 0, 1, ::i32::max_value];
436
437         let mut writer = MemWriter::new();
438         for i in ints.iter() {
439             writer.write_be_i32(*i);
440         }
441
442         let mut reader = MemReader::new(writer.unwrap());
443         for i in ints.iter() {
444             // this tests that the sign extension is working
445             // (comparing the values as i32 would not test this)
446             assert!(reader.read_be_int_n(4) == *i as i64);
447         }
448     }
449
450     #[test]
451     fn test_read_f32() {
452         //big-endian floating-point 8.1250
453         let buf = ~[0x41, 0x02, 0x00, 0x00];
454
455         let mut writer = MemWriter::new();
456         writer.write(buf);
457
458         let mut reader = MemReader::new(writer.unwrap());
459         let f = reader.read_be_f32();
460         assert!(f == 8.1250);
461     }
462
463     #[test]
464     fn test_read_write_f32() {
465         let f:f32 = 8.1250;
466
467         let mut writer = MemWriter::new();
468         writer.write_be_f32(f);
469         writer.write_le_f32(f);
470
471         let mut reader = MemReader::new(writer.unwrap());
472         assert!(reader.read_be_f32() == 8.1250);
473         assert!(reader.read_le_f32() == 8.1250);
474     }
475
476     #[test]
477     fn test_u64_from_be_bytes() {
478         use super::u64_from_be_bytes;
479
480         let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09];
481
482         // Aligned access
483         assert_eq!(u64_from_be_bytes(buf, 0, 0), 0);
484         assert_eq!(u64_from_be_bytes(buf, 0, 1), 0x01);
485         assert_eq!(u64_from_be_bytes(buf, 0, 2), 0x0102);
486         assert_eq!(u64_from_be_bytes(buf, 0, 3), 0x010203);
487         assert_eq!(u64_from_be_bytes(buf, 0, 4), 0x01020304);
488         assert_eq!(u64_from_be_bytes(buf, 0, 5), 0x0102030405);
489         assert_eq!(u64_from_be_bytes(buf, 0, 6), 0x010203040506);
490         assert_eq!(u64_from_be_bytes(buf, 0, 7), 0x01020304050607);
491         assert_eq!(u64_from_be_bytes(buf, 0, 8), 0x0102030405060708);
492
493         // Unaligned access
494         assert_eq!(u64_from_be_bytes(buf, 1, 0), 0);
495         assert_eq!(u64_from_be_bytes(buf, 1, 1), 0x02);
496         assert_eq!(u64_from_be_bytes(buf, 1, 2), 0x0203);
497         assert_eq!(u64_from_be_bytes(buf, 1, 3), 0x020304);
498         assert_eq!(u64_from_be_bytes(buf, 1, 4), 0x02030405);
499         assert_eq!(u64_from_be_bytes(buf, 1, 5), 0x0203040506);
500         assert_eq!(u64_from_be_bytes(buf, 1, 6), 0x020304050607);
501         assert_eq!(u64_from_be_bytes(buf, 1, 7), 0x02030405060708);
502         assert_eq!(u64_from_be_bytes(buf, 1, 8), 0x0203040506070809);
503     }
504 }
505
506 #[cfg(test)]
507 mod bench {
508     use extra::test::BenchHarness;
509     use container::Container;
510
511     macro_rules! u64_from_be_bytes_bench_impl(
512         ($size:expr, $stride:expr, $start_index:expr) =>
513         ({
514             use vec;
515             use super::u64_from_be_bytes;
516
517             let data = vec::from_fn($stride*100+$start_index, |i| i as u8);
518             let mut sum = 0u64;
519             bh.iter(|| {
520                 let mut i = $start_index;
521                 while (i < data.len()) {
522                     sum += u64_from_be_bytes(data, i, $size);
523                     i += $stride;
524                 }
525             });
526         })
527     )
528
529     #[bench]
530     fn u64_from_be_bytes_4_aligned(bh: &mut BenchHarness) {
531         u64_from_be_bytes_bench_impl!(4, 4, 0);
532     }
533
534     #[bench]
535     fn u64_from_be_bytes_4_unaligned(bh: &mut BenchHarness) {
536         u64_from_be_bytes_bench_impl!(4, 4, 1);
537     }
538
539     #[bench]
540     fn u64_from_be_bytes_7_aligned(bh: &mut BenchHarness) {
541         u64_from_be_bytes_bench_impl!(7, 8, 0);
542     }
543
544     #[bench]
545     fn u64_from_be_bytes_7_unaligned(bh: &mut BenchHarness) {
546         u64_from_be_bytes_bench_impl!(7, 8, 1);
547     }
548
549     #[bench]
550     fn u64_from_be_bytes_8_aligned(bh: &mut BenchHarness) {
551         u64_from_be_bytes_bench_impl!(8, 8, 0);
552     }
553
554     #[bench]
555     fn u64_from_be_bytes_8_unaligned(bh: &mut BenchHarness) {
556         u64_from_be_bytes_bench_impl!(8, 8, 1);
557     }
558 }