]> git.lizzy.rs Git - rust.git/blob - src/libcore/io.rs
35ffd88c8f477e9904eb79ed489cebe1aef5414d
[rust.git] / src / libcore / io.rs
1 // Copyright 2012 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 /*!
12
13 Basic input/output
14
15 */
16
17 use result::Result;
18
19 use int;
20 use libc;
21 use libc::{c_int, c_long, c_void, size_t, ssize_t};
22 use libc::consts::os::posix88::*;
23 use os;
24 use cast;
25 use path::Path;
26 use ops::Drop;
27 use ptr;
28 use result;
29 use str;
30 use uint;
31 use vec;
32
33 #[allow(non_camel_case_types)] // not sure what to do about this
34 pub type fd_t = c_int;
35
36 pub mod rustrt {
37     use libc;
38
39     #[abi = "cdecl"]
40     #[link_name = "rustrt"]
41     pub extern {
42         unsafe fn rust_get_stdin() -> *libc::FILE;
43         unsafe fn rust_get_stdout() -> *libc::FILE;
44         unsafe fn rust_get_stderr() -> *libc::FILE;
45     }
46 }
47
48 // Reading
49
50 // FIXME (#2004): This is all buffered. We might need an unbuffered variant
51 // as well
52 /**
53 * The SeekStyle enum describes the relationship between the position
54 * we'd like to seek to from our current position. It's used as an argument
55 * to the `seek` method defined on the `Reader` trait.
56 *
57 * There are three seek styles:
58 *
59 * 1. `SeekSet` means that the new position should become our position.
60 * 2. `SeekCur` means that we should seek from the current position.
61 * 3. `SeekEnd` means that we should seek from the end.
62 *
63 * # Examples
64 *
65 * None right now.
66 */
67 pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
68
69
70 /**
71 * The core Reader trait. All readers must implement this trait.
72 *
73 * # Examples
74 *
75 * None right now.
76 */
77 pub trait Reader {
78     // FIXME (#2004): Seekable really should be orthogonal.
79
80     // FIXME (#2982): This should probably return an error.
81     /**
82     * Reads bytes and puts them into `bytes`. Returns the number of
83     * bytes read.
84     *
85     * The number of bytes to be read is `len` or the end of the file,
86     * whichever comes first.
87     *
88     * The buffer must be at least `len` bytes long.
89     *
90     * # Examples
91     *
92     * None right now.
93     */
94     fn read(&self, bytes: &mut [u8], len: uint) -> uint;
95
96     /**
97     * Reads a single byte.
98     *
99     * In the case of an EOF or an error, returns a negative value.
100     *
101     * # Examples
102     *
103     * None right now.
104     */
105     fn read_byte(&self) -> int;
106
107     /**
108     * Returns a boolean value: are we currently at EOF?
109     *
110     * # Examples
111     *
112     * None right now.
113     */
114     fn eof(&self) -> bool;
115
116     /**
117     * Seek to a given `position` in the stream.
118     *
119     * Takes an optional SeekStyle, which affects how we seek from the
120     * position. See `SeekStyle` docs for more details.
121     *
122     * # Examples
123     *
124     * None right now.
125     */
126     fn seek(&self, position: int, style: SeekStyle);
127
128     /**
129     * Returns the current position within the stream.
130     *
131     * # Examples
132     *
133     * None right now.
134     */
135     fn tell(&self) -> uint;
136 }
137
138 impl Reader for @Reader {
139     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
140         self.read(bytes, len)
141     }
142     fn read_byte(&self) -> int {
143         self.read_byte()
144     }
145     fn eof(&self) -> bool {
146         self.eof()
147     }
148     fn seek(&self, position: int, style: SeekStyle) {
149         self.seek(position, style)
150     }
151     fn tell(&self) -> uint {
152         self.tell()
153     }
154 }
155
156 /**
157 * The `ReaderUtil` trait is a home for many of the utility functions
158 * a particular Reader should implement.
159 *
160 * The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
161 * on higher-level concepts like 'chars' and 'lines.'
162 *
163 * # Examples:
164 *
165 * None right now.
166 */
167 pub trait ReaderUtil {
168
169     /**
170     * Reads `len` number of bytes, and gives you a new vector back.
171     *
172     * # Examples
173     *
174     * None right now.
175     */
176     fn read_bytes(&self, len: uint) -> ~[u8];
177
178     /**
179     * Reads up until a specific byte is seen or EOF.
180     *
181     * The `include` parameter specifies if the character should be included
182     * in the returned string.
183     *
184     * # Examples
185     *
186     * None right now.
187     */
188     fn read_until(&self, c: u8, include: bool) -> ~str;
189
190     /**
191     * Reads up until the first '\n' or EOF.
192     *
193     * The '\n' is not included in the result.
194     *
195     * # Examples
196     *
197     * None right now.
198     */
199     fn read_line(&self) -> ~str;
200
201     /**
202     * Reads `n` chars.
203     *
204     * Assumes that those chars are UTF-8 encoded.
205     *
206     * The '\n' is not included in the result.
207     *
208     * # Examples
209     *
210     * None right now.
211     */
212     fn read_chars(&self, n: uint) -> ~[char];
213
214     /**
215     * Reads a single UTF-8 encoded char.
216     *
217     * # Examples
218     *
219     * None right now.
220     */
221     fn read_char(&self) -> char;
222
223     /**
224     * Reads up until the first null byte or EOF.
225     *
226     * The null byte is not returned.
227     *
228     * # Examples
229     *
230     * None right now.
231     */
232     fn read_c_str(&self) -> ~str;
233
234     /**
235     * Reads all remaining data in the stream.
236     *
237     * # Examples
238     *
239     * None right now.
240     */
241     fn read_whole_stream(&self) -> ~[u8];
242
243     /**
244     * Iterate over every byte until EOF or the iterator breaks.
245     *
246     * # Examples
247     *
248     * None right now.
249     */
250     fn each_byte(&self, it: &fn(int) -> bool);
251
252     /**
253     * Iterate over every char until EOF or the iterator breaks.
254     *
255     * # Examples
256     *
257     * None right now.
258     */
259     fn each_char(&self, it: &fn(char) -> bool);
260
261     /**
262     * Iterate over every line until EOF or the iterator breaks.
263     *
264     * # Examples
265     *
266     * None right now.
267     */
268     fn each_line(&self, it: &fn(&str) -> bool);
269
270     /**
271     * Reads all of the lines in the stream.
272     *
273     * Returns a vector of those lines.
274     *
275     * # Examples
276     *
277     * None right now.
278     */
279     fn read_lines(&self) -> ~[~str];
280
281     /**
282     * Reads `n` little-endian unsigned integer bytes.
283     *
284     * `n` must be between 1 and 8, inclusive.
285     *
286     * # Examples
287     *
288     * None right now.
289     */
290     fn read_le_uint_n(&self, nbytes: uint) -> u64;
291
292     /**
293     * Reads `n` little-endian signed integer bytes.
294     *
295     * `n` must be between 1 and 8, inclusive.
296     *
297     * # Examples
298     *
299     * None right now.
300     */
301     fn read_le_int_n(&self, nbytes: uint) -> i64;
302
303     /**
304     * Reads `n` big-endian unsigned integer bytes.
305     *
306     * `n` must be between 1 and 8, inclusive.
307     *
308     * # Examples
309     *
310     * None right now.
311     */
312     fn read_be_uint_n(&self, nbytes: uint) -> u64;
313
314     /**
315     * Reads `n` big-endian signed integer bytes.
316     *
317     * `n` must be between 1 and 8, inclusive.
318     *
319     * # Examples
320     *
321     * None right now.
322     */
323     fn read_be_int_n(&self, nbytes: uint) -> i64;
324
325     /**
326     * Reads a little-endian unsigned integer.
327     *
328     * The number of bytes returned is system-dependant.
329     *
330     * # Examples
331     *
332     * None right now.
333     */
334     fn read_le_uint(&self) -> uint;
335
336     /**
337     * Reads a little-endian integer.
338     *
339     * The number of bytes returned is system-dependant.
340     *
341     * # Examples
342     *
343     * None right now.
344     */
345     fn read_le_int(&self) -> int;
346
347     /**
348     * Reads a big-endian unsigned integer.
349     *
350     * The number of bytes returned is system-dependant.
351     *
352     * # Examples
353     *
354     * None right now.
355     */
356     fn read_be_uint(&self) -> uint;
357
358     /**
359     * Reads a big-endian integer.
360     *
361     * The number of bytes returned is system-dependant.
362     *
363     * # Examples
364     *
365     * None right now.
366     */
367     fn read_be_int(&self) -> int;
368
369     /**
370     * Reads a big-endian `u64`.
371     *
372     * `u64`s are 8 bytes long.
373     *
374     * # Examples
375     *
376     * None right now.
377     */
378     fn read_be_u64(&self) -> u64;
379
380     /**
381     * Reads a big-endian `u32`.
382     *
383     * `u32`s are 4 bytes long.
384     *
385     * # Examples
386     *
387     * None right now.
388     */
389     fn read_be_u32(&self) -> u32;
390
391     /**
392     * Reads a big-endian `u16`.
393     *
394     * `u16`s are 2 bytes long.
395     *
396     * # Examples
397     *
398     * None right now.
399     */
400     fn read_be_u16(&self) -> u16;
401
402     /**
403     * Reads a big-endian `i64`.
404     *
405     * `i64`s are 8 bytes long.
406     *
407     * # Examples
408     *
409     * None right now.
410     */
411     fn read_be_i64(&self) -> i64;
412
413     /**
414     * Reads a big-endian `i32`.
415     *
416     * `i32`s are 4 bytes long.
417     *
418     * # Examples
419     *
420     * None right now.
421     */
422     fn read_be_i32(&self) -> i32;
423
424     /**
425     * Reads a big-endian `i16`.
426     *
427     * `i16`s are 2 bytes long.
428     *
429     * # Examples
430     *
431     * None right now.
432     */
433     fn read_be_i16(&self) -> i16;
434
435     /**
436     * Reads a big-endian `f64`.
437     *
438     * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
439     *
440     * # Examples
441     *
442     * None right now.
443     */
444     fn read_be_f64(&self) -> f64;
445
446     /**
447     * Reads a big-endian `f32`.
448     *
449     * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
450     *
451     * # Examples
452     *
453     * None right now.
454     */
455     fn read_be_f32(&self) -> f32;
456
457     /**
458     * Reads a little-endian `u64`.
459     *
460     * `u64`s are 8 bytes long.
461     *
462     * # Examples
463     *
464     * None right now.
465     */
466     fn read_le_u64(&self) -> u64;
467
468     /**
469     * Reads a little-endian `u32`.
470     *
471     * `u32`s are 4 bytes long.
472     *
473     * # Examples
474     *
475     * None right now.
476     */
477     fn read_le_u32(&self) -> u32;
478
479     /**
480     * Reads a little-endian `u16`.
481     *
482     * `u16`s are 2 bytes long.
483     *
484     * # Examples
485     *
486     * None right now.
487     */
488     fn read_le_u16(&self) -> u16;
489
490     /**
491     * Reads a little-endian `i64`.
492     *
493     * `i64`s are 8 bytes long.
494     *
495     * # Examples
496     *
497     * None right now.
498     */
499     fn read_le_i64(&self) -> i64;
500
501     /**
502     * Reads a little-endian `i32`.
503     *
504     * `i32`s are 4 bytes long.
505     *
506     * # Examples
507     *
508     * None right now.
509     */
510     fn read_le_i32(&self) -> i32;
511
512     /**
513     * Reads a little-endian `i16`.
514     *
515     * `i16`s are 2 bytes long.
516     *
517     * # Examples
518     *
519     * None right now.
520     */
521     fn read_le_i16(&self) -> i16;
522
523     /**
524     * Reads a little-endian `f64`.
525     *
526     * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
527     *
528     * # Examples
529     *
530     * None right now.
531     */
532     fn read_le_f64(&self) -> f64;
533
534     /**
535     * Reads a little-endian `f32`.
536     *
537     * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
538     *
539     * # Examples
540     *
541     * None right now.
542     */
543     fn read_le_f32(&self) -> f32;
544
545     /**
546     * Read a u8.
547     *
548     * `u8`s are 1 byte.
549     *
550     * # Examples
551     *
552     * None right now.
553     */
554     fn read_u8(&self) -> u8;
555
556     /**
557     * Read an i8.
558     *
559     * `i8`s are 1 byte.
560     *
561     * # Examples
562     *
563     * None right now.
564     */
565     fn read_i8(&self) -> i8;
566 }
567
568 impl<T:Reader> ReaderUtil for T {
569
570     fn read_bytes(&self,len: uint) -> ~[u8] {
571         let mut bytes = vec::with_capacity(len);
572         unsafe { vec::raw::set_len(&mut bytes, len); }
573
574         let count = self.read(bytes, len);
575
576         unsafe { vec::raw::set_len(&mut bytes, count); }
577         bytes
578     }
579
580     fn read_until(&self, c: u8, include: bool) -> ~str {
581         let mut bytes = ~[];
582         loop {
583             let ch = self.read_byte();
584             if ch == -1 || ch == c as int {
585                 if include && ch == c as int {
586                     bytes.push(ch as u8);
587                 }
588                 break;
589             }
590             bytes.push(ch as u8);
591         }
592         str::from_bytes(bytes)
593     }
594
595     fn read_line(&self) -> ~str {
596         self.read_until('\n' as u8, false)
597     }
598
599     fn read_chars(&self, n: uint) -> ~[char] {
600         // returns the (consumed offset, n_req), appends characters to &chars
601         fn chars_from_bytes<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
602             -> (uint, uint) {
603             let mut i = 0;
604             let bytes_len = bytes.len();
605             while i < bytes_len {
606                 let b0 = bytes[i];
607                 let w = str::utf8_char_width(b0);
608                 let end = i + w;
609                 i += 1;
610                 assert!((w > 0));
611                 if w == 1 {
612                     chars.push(b0 as char);
613                     loop;
614                 }
615                 // can't satisfy this char with the existing data
616                 if end > bytes_len {
617                     return (i - 1, end - bytes_len);
618                 }
619                 let mut val = 0;
620                 while i < end {
621                     let next = bytes[i] as int;
622                     i += 1;
623                     assert!((next > -1));
624                     assert!((next & 192 == 128));
625                     val <<= 6;
626                     val += (next & 63) as uint;
627                 }
628                 // See str::char_at
629                 val += ((b0 << ((w + 1) as u8)) as uint)
630                     << (w - 1) * 6 - w - 1u;
631                 chars.push(val as char);
632             }
633             return (i, 0);
634         }
635         let mut bytes = ~[];
636         let mut chars = ~[];
637         // might need more bytes, but reading n will never over-read
638         let mut nbread = n;
639         while nbread > 0 {
640             let data = self.read_bytes(nbread);
641             if data.is_empty() {
642                 // eof - FIXME (#2004): should we do something if
643                 // we're split in a unicode char?
644                 break;
645             }
646             bytes.push_all(data);
647             let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars);
648             let ncreq = n - chars.len();
649             // again we either know we need a certain number of bytes
650             // to complete a character, or we make sure we don't
651             // over-read by reading 1-byte per char needed
652             nbread = if ncreq > nbreq { ncreq } else { nbreq };
653             if nbread > 0 {
654                 bytes = vec::slice(bytes, offset, bytes.len()).to_vec();
655             }
656         }
657         chars
658     }
659
660     fn read_char(&self) -> char {
661         let c = self.read_chars(1);
662         if vec::len(c) == 0 {
663             return -1 as char; // FIXME will this stay valid? // #2004
664         }
665         assert!((vec::len(c) == 1));
666         return c[0];
667     }
668
669     fn read_c_str(&self) -> ~str {
670         self.read_until(0u8, false)
671     }
672
673     fn read_whole_stream(&self) -> ~[u8] {
674         let mut bytes: ~[u8] = ~[];
675         while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
676         bytes
677     }
678
679     fn each_byte(&self, it: &fn(int) -> bool) {
680         while !self.eof() {
681             if !it(self.read_byte()) { break; }
682         }
683     }
684
685     fn each_char(&self, it: &fn(char) -> bool) {
686         while !self.eof() {
687             if !it(self.read_char()) { break; }
688         }
689     }
690
691     fn each_line(&self, it: &fn(s: &str) -> bool) {
692         while !self.eof() {
693             // include the \n, so that we can distinguish an entirely empty
694             // line read after "...\n", and the trailing empty line in
695             // "...\n\n".
696             let mut line = self.read_until('\n' as u8, true);
697
698             // blank line at the end of the reader is ignored
699             if self.eof() && line.is_empty() { break; }
700
701             // trim the \n, so that each_line is consistent with read_line
702             let n = str::len(line);
703             if line[n-1] == '\n' as u8 {
704                 unsafe { str::raw::set_len(&mut line, n-1); }
705             }
706
707             if !it(line) { break; }
708         }
709     }
710
711     fn read_lines(&self) -> ~[~str] {
712         do vec::build |push| {
713             for self.each_line |line| {
714                 push(str::from_slice(line));
715             }
716         }
717     }
718
719     // FIXME int reading methods need to deal with eof - issue #2004
720
721     fn read_le_uint_n(&self, nbytes: uint) -> u64 {
722         assert!(nbytes > 0 && nbytes <= 8);
723
724         let mut val = 0u64, pos = 0, i = nbytes;
725         while i > 0 {
726             val += (self.read_u8() as u64) << pos;
727             pos += 8;
728             i -= 1;
729         }
730         val
731     }
732
733     fn read_le_int_n(&self, nbytes: uint) -> i64 {
734         extend_sign(self.read_le_uint_n(nbytes), nbytes)
735     }
736
737     fn read_be_uint_n(&self, nbytes: uint) -> u64 {
738         assert!(nbytes > 0 && nbytes <= 8);
739
740         let mut val = 0u64, i = nbytes;
741         while i > 0 {
742             i -= 1;
743             val += (self.read_u8() as u64) << i * 8;
744         }
745         val
746     }
747
748     fn read_be_int_n(&self, nbytes: uint) -> i64 {
749         extend_sign(self.read_be_uint_n(nbytes), nbytes)
750     }
751
752     fn read_le_uint(&self) -> uint {
753         self.read_le_uint_n(uint::bytes) as uint
754     }
755
756     fn read_le_int(&self) -> int {
757         self.read_le_int_n(int::bytes) as int
758     }
759
760     fn read_be_uint(&self) -> uint {
761         self.read_be_uint_n(uint::bytes) as uint
762     }
763
764     fn read_be_int(&self) -> int {
765         self.read_be_int_n(int::bytes) as int
766     }
767
768     fn read_be_u64(&self) -> u64 {
769         self.read_be_uint_n(8) as u64
770     }
771
772     fn read_be_u32(&self) -> u32 {
773         self.read_be_uint_n(4) as u32
774     }
775
776     fn read_be_u16(&self) -> u16 {
777         self.read_be_uint_n(2) as u16
778     }
779
780     fn read_be_i64(&self) -> i64 {
781         self.read_be_int_n(8) as i64
782     }
783
784     fn read_be_i32(&self) -> i32 {
785         self.read_be_int_n(4) as i32
786     }
787
788     fn read_be_i16(&self) -> i16 {
789         self.read_be_int_n(2) as i16
790     }
791
792     fn read_be_f64(&self) -> f64 {
793         unsafe {
794             cast::transmute::<u64, f64>(self.read_be_u64())
795         }
796     }
797
798     fn read_be_f32(&self) -> f32 {
799         unsafe {
800             cast::transmute::<u32, f32>(self.read_be_u32())
801         }
802     }
803
804     fn read_le_u64(&self) -> u64 {
805         self.read_le_uint_n(8) as u64
806     }
807
808     fn read_le_u32(&self) -> u32 {
809         self.read_le_uint_n(4) as u32
810     }
811
812     fn read_le_u16(&self) -> u16 {
813         self.read_le_uint_n(2) as u16
814     }
815
816     fn read_le_i64(&self) -> i64 {
817         self.read_le_int_n(8) as i64
818     }
819
820     fn read_le_i32(&self) -> i32 {
821         self.read_le_int_n(4) as i32
822     }
823
824     fn read_le_i16(&self) -> i16 {
825         self.read_le_int_n(2) as i16
826     }
827
828     fn read_le_f64(&self) -> f64 {
829         unsafe {
830             cast::transmute::<u64, f64>(self.read_le_u64())
831         }
832     }
833
834     fn read_le_f32(&self) -> f32 {
835         unsafe {
836             cast::transmute::<u32, f32>(self.read_le_u32())
837         }
838     }
839
840     fn read_u8(&self) -> u8 {
841         self.read_byte() as u8
842     }
843
844     fn read_i8(&self) -> i8 {
845         self.read_byte() as i8
846     }
847 }
848
849 fn extend_sign(val: u64, nbytes: uint) -> i64 {
850     let shift = (8 - nbytes) * 8;
851     (val << shift) as i64 >> shift
852 }
853
854 // Reader implementations
855
856 fn convert_whence(whence: SeekStyle) -> i32 {
857     return match whence {
858       SeekSet => 0i32,
859       SeekCur => 1i32,
860       SeekEnd => 2i32
861     };
862 }
863
864 impl Reader for *libc::FILE {
865     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
866         unsafe {
867             do vec::as_mut_buf(bytes) |buf_p, buf_len| {
868                 assert!(buf_len >= len);
869
870                 let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
871                                         len as size_t, *self);
872
873                 count as uint
874             }
875         }
876     }
877     fn read_byte(&self) -> int {
878         unsafe {
879             libc::fgetc(*self) as int
880         }
881     }
882     fn eof(&self) -> bool {
883         unsafe {
884             return libc::feof(*self) != 0 as c_int;
885         }
886     }
887     fn seek(&self, offset: int, whence: SeekStyle) {
888         unsafe {
889             assert!(libc::fseek(*self,
890                                      offset as c_long,
891                                      convert_whence(whence)) == 0 as c_int);
892         }
893     }
894     fn tell(&self) -> uint {
895         unsafe {
896             return libc::ftell(*self) as uint;
897         }
898     }
899 }
900
901 struct Wrapper<T, C> {
902     base: T,
903     cleanup: C,
904 }
905
906 // A forwarding impl of reader that also holds on to a resource for the
907 // duration of its lifetime.
908 // FIXME there really should be a better way to do this // #2004
909 impl<R:Reader,C> Reader for Wrapper<R, C> {
910     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
911         self.base.read(bytes, len)
912     }
913     fn read_byte(&self) -> int { self.base.read_byte() }
914     fn eof(&self) -> bool { self.base.eof() }
915     fn seek(&self, off: int, whence: SeekStyle) {
916         self.base.seek(off, whence)
917     }
918     fn tell(&self) -> uint { self.base.tell() }
919 }
920
921 pub struct FILERes {
922     f: *libc::FILE,
923 }
924
925 impl Drop for FILERes {
926     fn finalize(&self) {
927         unsafe {
928             libc::fclose(self.f);
929         }
930     }
931 }
932
933 pub fn FILERes(f: *libc::FILE) -> FILERes {
934     FILERes {
935         f: f
936     }
937 }
938
939 pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
940     if cleanup {
941         @Wrapper { base: f, cleanup: FILERes(f) } as @Reader
942     } else {
943         @f as @Reader
944     }
945 }
946
947 // FIXME (#2004): this should either be an trait-less impl, a set of
948 // top-level functions that take a reader, or a set of default methods on
949 // reader (which can then be called reader)
950
951 pub fn stdin() -> @Reader {
952     unsafe {
953         @rustrt::rust_get_stdin() as @Reader
954     }
955 }
956
957 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
958     unsafe {
959         let f = os::as_c_charp(path.to_str(), |pathbuf| {
960             os::as_c_charp("r", |modebuf|
961                 libc::fopen(pathbuf, modebuf)
962             )
963         });
964         return if f as uint == 0u { result::Err(~"error opening "
965                                                 + path.to_str()) }
966         else {
967             result::Ok(FILE_reader(f, true))
968         }
969     }
970 }
971
972
973 // Byte readers
974 pub struct BytesReader<'self> {
975     bytes: &'self [u8],
976     mut pos: uint
977 }
978
979 impl<'self> Reader for BytesReader<'self> {
980     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
981         let count = uint::min(len, self.bytes.len() - self.pos);
982
983         let view = vec::slice(self.bytes, self.pos, self.bytes.len());
984         vec::bytes::copy_memory(bytes, view, count);
985
986         self.pos += count;
987
988         count
989     }
990     fn read_byte(&self) -> int {
991         if self.pos == self.bytes.len() { return -1; }
992         let b = self.bytes[self.pos];
993         self.pos += 1u;
994         return b as int;
995     }
996     fn eof(&self) -> bool { self.pos == self.bytes.len() }
997     fn seek(&self, offset: int, whence: SeekStyle) {
998         let pos = self.pos;
999         self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
1000     }
1001     fn tell(&self) -> uint { self.pos }
1002 }
1003
1004 pub fn with_bytes_reader<t>(bytes: &[u8], f: &fn(@Reader) -> t) -> t {
1005     f(@BytesReader { bytes: bytes, pos: 0u } as @Reader)
1006 }
1007
1008 pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
1009     str::byte_slice(s, |bytes| with_bytes_reader(bytes, f))
1010 }
1011
1012 // Writing
1013 pub enum FileFlag { Append, Create, Truncate, NoFlag, }
1014
1015 // What type of writer are we?
1016 #[deriving(Eq)]
1017 pub enum WriterType { Screen, File }
1018
1019 // FIXME (#2004): Seekable really should be orthogonal.
1020 // FIXME (#2004): eventually u64
1021 /// The raw underlying writer trait. All writers must implement this.
1022 pub trait Writer {
1023
1024     /// Write all of the given bytes.
1025     fn write(&self, v: &const [u8]);
1026
1027     /// Move the current position within the stream. The second parameter
1028     /// determines the position that the first parameter is relative to.
1029     fn seek(&self, int, SeekStyle);
1030
1031     /// Return the current position within the stream.
1032     fn tell(&self) -> uint;
1033
1034     /// Flush the output buffer for this stream (if there is one).
1035     fn flush(&self) -> int;
1036
1037     /// Determine if this Writer is writing to a file or not.
1038     fn get_type(&self) -> WriterType;
1039 }
1040
1041 impl Writer for @Writer {
1042     fn write(&self, v: &const [u8]) { self.write(v) }
1043     fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
1044     fn tell(&self) -> uint { self.tell() }
1045     fn flush(&self) -> int { self.flush() }
1046     fn get_type(&self) -> WriterType { self.get_type() }
1047 }
1048
1049 impl<W:Writer,C> Writer for Wrapper<W, C> {
1050     fn write(&self, bs: &const [u8]) { self.base.write(bs); }
1051     fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
1052     fn tell(&self) -> uint { self.base.tell() }
1053     fn flush(&self) -> int { self.base.flush() }
1054     fn get_type(&self) -> WriterType { File }
1055 }
1056
1057 impl Writer for *libc::FILE {
1058     fn write(&self, v: &const [u8]) {
1059         unsafe {
1060             do vec::as_const_buf(v) |vbuf, len| {
1061                 let nout = libc::fwrite(vbuf as *c_void,
1062                                         1,
1063                                         len as size_t,
1064                                         *self);
1065                 if nout != len as size_t {
1066                     error!("error writing buffer");
1067                     error!("%s", os::last_os_error());
1068                     fail!();
1069                 }
1070             }
1071         }
1072     }
1073     fn seek(&self, offset: int, whence: SeekStyle) {
1074         unsafe {
1075             assert!(libc::fseek(*self,
1076                                      offset as c_long,
1077                                      convert_whence(whence)) == 0 as c_int);
1078         }
1079     }
1080     fn tell(&self) -> uint {
1081         unsafe {
1082             libc::ftell(*self) as uint
1083         }
1084     }
1085     fn flush(&self) -> int {
1086         unsafe {
1087             libc::fflush(*self) as int
1088         }
1089     }
1090     fn get_type(&self) -> WriterType {
1091         unsafe {
1092             let fd = libc::fileno(*self);
1093             if libc::isatty(fd) == 0 { File   }
1094             else                     { Screen }
1095         }
1096     }
1097 }
1098
1099 pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
1100     if cleanup {
1101         @Wrapper { base: f, cleanup: FILERes(f) } as @Writer
1102     } else {
1103         @f as @Writer
1104     }
1105 }
1106
1107 impl Writer for fd_t {
1108     fn write(&self, v: &const [u8]) {
1109         unsafe {
1110             let mut count = 0u;
1111             do vec::as_const_buf(v) |vbuf, len| {
1112                 while count < len {
1113                     let vb = ptr::const_offset(vbuf, count) as *c_void;
1114                     let nout = libc::write(*self, vb, len as size_t);
1115                     if nout < 0 as ssize_t {
1116                         error!("error writing buffer");
1117                         error!("%s", os::last_os_error());
1118                         fail!();
1119                     }
1120                     count += nout as uint;
1121                 }
1122             }
1123         }
1124     }
1125     fn seek(&self, _offset: int, _whence: SeekStyle) {
1126         error!("need 64-bit foreign calls for seek, sorry");
1127         fail!();
1128     }
1129     fn tell(&self) -> uint {
1130         error!("need 64-bit foreign calls for tell, sorry");
1131         fail!();
1132     }
1133     fn flush(&self) -> int { 0 }
1134     fn get_type(&self) -> WriterType {
1135         unsafe {
1136             if libc::isatty(*self) == 0 { File } else { Screen }
1137         }
1138     }
1139 }
1140
1141 pub struct FdRes {
1142     fd: fd_t,
1143 }
1144
1145 impl Drop for FdRes {
1146     fn finalize(&self) {
1147         unsafe {
1148             libc::close(self.fd);
1149         }
1150     }
1151 }
1152
1153 pub fn FdRes(fd: fd_t) -> FdRes {
1154     FdRes {
1155         fd: fd
1156     }
1157 }
1158
1159 pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
1160     if cleanup {
1161         @Wrapper { base: fd, cleanup: FdRes(fd) } as @Writer
1162     } else {
1163         @fd as @Writer
1164     }
1165 }
1166
1167
1168 pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
1169                    -> Result<@Writer, ~str> {
1170     #[cfg(windows)]
1171     fn wb() -> c_int {
1172       (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
1173     }
1174
1175     #[cfg(unix)]
1176     fn wb() -> c_int { O_WRONLY as c_int }
1177
1178     let mut fflags: c_int = wb();
1179     for vec::each(flags) |f| {
1180         match *f {
1181           Append => fflags |= O_APPEND as c_int,
1182           Create => fflags |= O_CREAT as c_int,
1183           Truncate => fflags |= O_TRUNC as c_int,
1184           NoFlag => ()
1185         }
1186     }
1187     let fd = unsafe {
1188         do os::as_c_charp(path.to_str()) |pathbuf| {
1189             libc::open(pathbuf, fflags,
1190                        (S_IRUSR | S_IWUSR) as c_int)
1191         }
1192     };
1193     if fd < (0 as c_int) {
1194         result::Err(fmt!("error opening %s: %s", path.to_str(),
1195                          os::last_os_error()))
1196     } else {
1197         result::Ok(fd_writer(fd, true))
1198     }
1199 }
1200
1201 pub fn u64_to_le_bytes<T>(n: u64, size: uint,
1202                           f: &fn(v: &[u8]) -> T) -> T {
1203     assert!(size <= 8u);
1204     match size {
1205       1u => f(&[n as u8]),
1206       2u => f(&[n as u8,
1207               (n >> 8) as u8]),
1208       4u => f(&[n as u8,
1209               (n >> 8) as u8,
1210               (n >> 16) as u8,
1211               (n >> 24) as u8]),
1212       8u => f(&[n as u8,
1213               (n >> 8) as u8,
1214               (n >> 16) as u8,
1215               (n >> 24) as u8,
1216               (n >> 32) as u8,
1217               (n >> 40) as u8,
1218               (n >> 48) as u8,
1219               (n >> 56) as u8]),
1220       _ => {
1221
1222         let mut bytes: ~[u8] = ~[], i = size, n = n;
1223         while i > 0u {
1224             bytes.push((n & 255_u64) as u8);
1225             n >>= 8_u64;
1226             i -= 1u;
1227         }
1228         f(bytes)
1229       }
1230     }
1231 }
1232
1233 pub fn u64_to_be_bytes<T>(n: u64, size: uint,
1234                            f: &fn(v: &[u8]) -> T) -> T {
1235     assert!(size <= 8u);
1236     match size {
1237       1u => f(&[n as u8]),
1238       2u => f(&[(n >> 8) as u8,
1239               n as u8]),
1240       4u => f(&[(n >> 24) as u8,
1241               (n >> 16) as u8,
1242               (n >> 8) as u8,
1243               n as u8]),
1244       8u => f(&[(n >> 56) as u8,
1245               (n >> 48) as u8,
1246               (n >> 40) as u8,
1247               (n >> 32) as u8,
1248               (n >> 24) as u8,
1249               (n >> 16) as u8,
1250               (n >> 8) as u8,
1251               n as u8]),
1252       _ => {
1253         let mut bytes: ~[u8] = ~[];
1254         let mut i = size;
1255         while i > 0u {
1256             let shift = ((i - 1u) * 8u) as u64;
1257             bytes.push((n >> shift) as u8);
1258             i -= 1u;
1259         }
1260         f(bytes)
1261       }
1262     }
1263 }
1264
1265 pub fn u64_from_be_bytes(data: &const [u8],
1266                          start: uint,
1267                          size: uint)
1268                       -> u64 {
1269     let mut sz = size;
1270     assert!((sz <= 8u));
1271     let mut val = 0_u64;
1272     let mut pos = start;
1273     while sz > 0u {
1274         sz -= 1u;
1275         val += (data[pos] as u64) << ((sz * 8u) as u64);
1276         pos += 1u;
1277     }
1278     return val;
1279 }
1280
1281 // FIXME: #3048 combine trait+impl (or just move these to
1282 // default methods on writer)
1283 /// Generic utility functions defined on writers.
1284 pub trait WriterUtil {
1285
1286     /// Write a single utf-8 encoded char.
1287     fn write_char(&self, ch: char);
1288
1289     /// Write every char in the given str, encoded as utf-8.
1290     fn write_str(&self, s: &str);
1291
1292     /// Write the given str, as utf-8, followed by '\n'.
1293     fn write_line(&self, s: &str);
1294
1295     /// Write the result of passing n through `int::to_str_bytes`.
1296     fn write_int(&self, n: int);
1297
1298     /// Write the result of passing n through `uint::to_str_bytes`.
1299     fn write_uint(&self, n: uint);
1300
1301     /// Write a little-endian uint (number of bytes depends on system).
1302     fn write_le_uint(&self, n: uint);
1303
1304     /// Write a little-endian int (number of bytes depends on system).
1305     fn write_le_int(&self, n: int);
1306
1307     /// Write a big-endian uint (number of bytes depends on system).
1308     fn write_be_uint(&self, n: uint);
1309
1310     /// Write a big-endian int (number of bytes depends on system).
1311     fn write_be_int(&self, n: int);
1312
1313     /// Write a big-endian u64 (8 bytes).
1314     fn write_be_u64(&self, n: u64);
1315
1316     /// Write a big-endian u32 (4 bytes).
1317     fn write_be_u32(&self, n: u32);
1318
1319     /// Write a big-endian u16 (2 bytes).
1320     fn write_be_u16(&self, n: u16);
1321
1322     /// Write a big-endian i64 (8 bytes).
1323     fn write_be_i64(&self, n: i64);
1324
1325     /// Write a big-endian i32 (4 bytes).
1326     fn write_be_i32(&self, n: i32);
1327
1328     /// Write a big-endian i16 (2 bytes).
1329     fn write_be_i16(&self, n: i16);
1330
1331     /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
1332     fn write_be_f64(&self, f: f64);
1333
1334     /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
1335     fn write_be_f32(&self, f: f32);
1336
1337     /// Write a little-endian u64 (8 bytes).
1338     fn write_le_u64(&self, n: u64);
1339
1340     /// Write a little-endian u32 (4 bytes).
1341     fn write_le_u32(&self, n: u32);
1342
1343     /// Write a little-endian u16 (2 bytes).
1344     fn write_le_u16(&self, n: u16);
1345
1346     /// Write a little-endian i64 (8 bytes).
1347     fn write_le_i64(&self, n: i64);
1348
1349     /// Write a little-endian i32 (4 bytes).
1350     fn write_le_i32(&self, n: i32);
1351
1352     /// Write a little-endian i16 (2 bytes).
1353     fn write_le_i16(&self, n: i16);
1354
1355     /// Write a little-endian IEEE754 double-precision floating-point
1356     /// (8 bytes).
1357     fn write_le_f64(&self, f: f64);
1358
1359     /// Write a litten-endian IEEE754 single-precision floating-point
1360     /// (4 bytes).
1361     fn write_le_f32(&self, f: f32);
1362
1363     /// Write a u8 (1 byte).
1364     fn write_u8(&self, n: u8);
1365
1366     /// Write a i8 (1 byte).
1367     fn write_i8(&self, n: i8);
1368 }
1369
1370 impl<T:Writer> WriterUtil for T {
1371     fn write_char(&self, ch: char) {
1372         if (ch as uint) < 128u {
1373             self.write(&[ch as u8]);
1374         } else {
1375             self.write_str(str::from_char(ch));
1376         }
1377     }
1378     fn write_str(&self, s: &str) { str::byte_slice(s, |v| self.write(v)) }
1379     fn write_line(&self, s: &str) {
1380         self.write_str(s);
1381         self.write_str(&"\n");
1382     }
1383     fn write_int(&self, n: int) {
1384         int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1385     }
1386     fn write_uint(&self, n: uint) {
1387         uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
1388     }
1389     fn write_le_uint(&self, n: uint) {
1390         u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
1391     }
1392     fn write_le_int(&self, n: int) {
1393         u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
1394     }
1395     fn write_be_uint(&self, n: uint) {
1396         u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
1397     }
1398     fn write_be_int(&self, n: int) {
1399         u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
1400     }
1401     fn write_be_u64(&self, n: u64) {
1402         u64_to_be_bytes(n, 8u, |v| self.write(v))
1403     }
1404     fn write_be_u32(&self, n: u32) {
1405         u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1406     }
1407     fn write_be_u16(&self, n: u16) {
1408         u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1409     }
1410     fn write_be_i64(&self, n: i64) {
1411         u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
1412     }
1413     fn write_be_i32(&self, n: i32) {
1414         u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
1415     }
1416     fn write_be_i16(&self, n: i16) {
1417         u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
1418     }
1419     fn write_be_f64(&self, f:f64) {
1420         unsafe {
1421             self.write_be_u64(cast::transmute(f))
1422         }
1423     }
1424     fn write_be_f32(&self, f:f32) {
1425         unsafe {
1426             self.write_be_u32(cast::transmute(f))
1427         }
1428     }
1429     fn write_le_u64(&self, n: u64) {
1430         u64_to_le_bytes(n, 8u, |v| self.write(v))
1431     }
1432     fn write_le_u32(&self, n: u32) {
1433         u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1434     }
1435     fn write_le_u16(&self, n: u16) {
1436         u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1437     }
1438     fn write_le_i64(&self, n: i64) {
1439         u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
1440     }
1441     fn write_le_i32(&self, n: i32) {
1442         u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
1443     }
1444     fn write_le_i16(&self, n: i16) {
1445         u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
1446     }
1447     fn write_le_f64(&self, f:f64) {
1448         unsafe {
1449             self.write_le_u64(cast::transmute(f))
1450         }
1451     }
1452     fn write_le_f32(&self, f:f32) {
1453         unsafe {
1454             self.write_le_u32(cast::transmute(f))
1455         }
1456     }
1457
1458     fn write_u8(&self, n: u8) { self.write([n]) }
1459     fn write_i8(&self, n: i8) { self.write([n as u8]) }
1460
1461 }
1462
1463 #[allow(non_implicitly_copyable_typarams)]
1464 pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
1465     mk_file_writer(path, flags).chain(|w| result::Ok(w))
1466 }
1467
1468
1469 // FIXME: fileflags // #2004
1470 pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
1471     unsafe {
1472         let f = do os::as_c_charp(path.to_str()) |pathbuf| {
1473             do os::as_c_charp("w") |modebuf| {
1474                 libc::fopen(pathbuf, modebuf)
1475             }
1476         };
1477         return if f as uint == 0u {
1478             result::Err(~"error opening " + path.to_str())
1479         } else {
1480             result::Ok(FILE_writer(f, true))
1481         }
1482     }
1483 }
1484
1485 // FIXME (#2004) it would be great if this could be a const
1486 // FIXME (#2004) why are these different from the way stdin() is
1487 // implemented?
1488 pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
1489 pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
1490
1491 pub fn print(s: &str) { stdout().write_str(s); }
1492 pub fn println(s: &str) { stdout().write_line(s); }
1493
1494 pub struct BytesWriter {
1495     mut bytes: ~[u8],
1496     mut pos: uint,
1497 }
1498
1499 impl Writer for BytesWriter {
1500     fn write(&self, v: &const [u8]) {
1501         let v_len = v.len();
1502         let bytes_len = vec::uniq_len(&const self.bytes);
1503
1504         let count = uint::max(bytes_len, self.pos + v_len);
1505         vec::reserve(&mut self.bytes, count);
1506
1507         unsafe {
1508             vec::raw::set_len(&mut self.bytes, count);
1509             let view = vec::mut_slice(self.bytes, self.pos, count);
1510             vec::bytes::copy_memory(view, v, v_len);
1511         }
1512
1513         self.pos += v_len;
1514     }
1515     fn seek(&self, offset: int, whence: SeekStyle) {
1516         let pos = self.pos;
1517         let len = vec::uniq_len(&const self.bytes);
1518         self.pos = seek_in_buf(offset, pos, len, whence);
1519     }
1520     fn tell(&self) -> uint { self.pos }
1521     fn flush(&self) -> int { 0 }
1522     fn get_type(&self) -> WriterType { File }
1523 }
1524
1525 pub fn BytesWriter() -> BytesWriter {
1526     BytesWriter { bytes: ~[], mut pos: 0u }
1527 }
1528
1529 pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
1530     let wr = @BytesWriter();
1531     f(wr as @Writer);
1532     let @BytesWriter{bytes, _} = wr;
1533     return bytes;
1534 }
1535
1536 pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
1537     let mut v = with_bytes_writer(f);
1538
1539     // Make sure the vector has a trailing null and is proper utf8.
1540     v.push(0);
1541     assert!(str::is_utf8(v));
1542
1543     unsafe { ::cast::transmute(v) }
1544 }
1545
1546 // Utility functions
1547 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1548    uint {
1549     let mut bpos = pos as int;
1550     let blen = len as int;
1551     match whence {
1552       SeekSet => bpos = offset,
1553       SeekCur => bpos += offset,
1554       SeekEnd => bpos = blen + offset
1555     }
1556     if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
1557     return bpos as uint;
1558 }
1559
1560 #[allow(non_implicitly_copyable_typarams)]
1561 pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
1562     result::chain(read_whole_file(file), |bytes| {
1563         if str::is_utf8(bytes) {
1564             result::Ok(str::from_bytes(bytes))
1565        } else {
1566            result::Err(file.to_str() + ~" is not UTF-8")
1567        }
1568     })
1569 }
1570
1571 // FIXME (#2004): implement this in a low-level way. Going through the
1572 // abstractions is pointless.
1573 #[allow(non_implicitly_copyable_typarams)]
1574 pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
1575     result::chain(file_reader(file), |rdr| {
1576         result::Ok(rdr.read_whole_stream())
1577     })
1578 }
1579
1580 // fsync related
1581
1582 pub mod fsync {
1583     use io::{FILERes, FdRes, fd_t};
1584     use kinds::Copy;
1585     use libc;
1586     use ops::Drop;
1587     use option::{None, Option, Some};
1588     use os;
1589
1590     pub enum Level {
1591         // whatever fsync does on that platform
1592         FSync,
1593
1594         // fdatasync on linux, similiar or more on other platforms
1595         FDataSync,
1596
1597         // full fsync
1598         //
1599         // You must additionally sync the parent directory as well!
1600         FullFSync,
1601     }
1602
1603
1604     // Artifacts that need to fsync on destruction
1605     pub struct Res<t> {
1606         arg: Arg<t>,
1607     }
1608
1609     #[unsafe_destructor]
1610     impl<T:Copy> Drop for Res<T> {
1611         fn finalize(&self) {
1612             match self.arg.opt_level {
1613                 None => (),
1614                 Some(level) => {
1615                   // fail hard if not succesful
1616                   assert!(((self.arg.fsync_fn)(self.arg.val, level)
1617                     != -1));
1618                 }
1619             }
1620         }
1621     }
1622
1623     pub fn Res<t: Copy>(arg: Arg<t>) -> Res<t>{
1624         Res {
1625             arg: arg
1626         }
1627     }
1628
1629     pub struct Arg<t> {
1630         val: t,
1631         opt_level: Option<Level>,
1632         fsync_fn: @fn(f: t, Level) -> int,
1633     }
1634
1635     // fsync file after executing blk
1636     // FIXME (#2004) find better way to create resources within lifetime of
1637     // outer res
1638     pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
1639                          blk: &fn(v: Res<*libc::FILE>)) {
1640         blk(Res(Arg {
1641             val: file.f, opt_level: opt_level,
1642             fsync_fn: |file, l| {
1643                 unsafe {
1644                     os::fsync_fd(libc::fileno(file), l) as int
1645                 }
1646             }
1647         }));
1648     }
1649
1650     // fsync fd after executing blk
1651     pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1652                        blk: &fn(v: Res<fd_t>)) {
1653         blk(Res(Arg {
1654             val: fd.fd, opt_level: opt_level,
1655             fsync_fn: |fd, l| os::fsync_fd(fd, l) as int
1656         }));
1657     }
1658
1659     // Type of objects that may want to fsync
1660     pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1661
1662     // Call o.fsync after executing blk
1663     pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
1664                     blk: &fn(v: Res<@FSyncable>)) {
1665         blk(Res(Arg {
1666             val: o, opt_level: opt_level,
1667             fsync_fn: |o, l| o.fsync(l)
1668         }));
1669     }
1670 }
1671
1672 #[cfg(test)]
1673 mod tests {
1674     use i32;
1675     use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
1676     use io;
1677     use path::Path;
1678     use result;
1679     use str;
1680     use u64;
1681     use vec;
1682
1683     #[test]
1684     fn test_simple() {
1685         let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
1686         debug!(tmpfile);
1687         let frood: ~str =
1688             ~"A hoopy frood who really knows where his towel is.";
1689         debug!(copy frood);
1690         {
1691             let out: @io::Writer =
1692                 result::get(
1693                     &io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
1694             out.write_str(frood);
1695         }
1696         let inp: @io::Reader = result::get(&io::file_reader(tmpfile));
1697         let frood2: ~str = inp.read_c_str();
1698         debug!(copy frood2);
1699         assert!(frood == frood2);
1700     }
1701
1702     #[test]
1703     fn test_readchars_empty() {
1704         do io::with_str_reader(~"") |inp| {
1705             let res : ~[char] = inp.read_chars(128);
1706             assert!((vec::len(res) == 0));
1707         }
1708     }
1709
1710     #[test]
1711     fn test_read_line_utf8() {
1712         do io::with_str_reader(~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
1713             let line = inp.read_line();
1714             assert!(line == ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
1715         }
1716     }
1717
1718     #[test]
1719     fn test_read_lines() {
1720         do io::with_str_reader(~"a\nb\nc\n") |inp| {
1721             assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]);
1722         }
1723
1724         do io::with_str_reader(~"a\nb\nc") |inp| {
1725             assert!(inp.read_lines() == ~[~"a", ~"b", ~"c"]);
1726         }
1727
1728         do io::with_str_reader(~"") |inp| {
1729             assert!(inp.read_lines().is_empty());
1730         }
1731     }
1732
1733     #[test]
1734     fn test_readchars_wide() {
1735         let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1736         let ivals : ~[int] = ~[
1737             29983, 38152, 30340, 27748,
1738             21273, 20999, 32905, 27748,
1739             104, 101, 108, 108, 111,
1740             29983, 38152, 30340, 27748,
1741             21273, 20999, 32905, 27748];
1742         fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
1743             do io::with_str_reader(s) |inp| {
1744                 let res : ~[char] = inp.read_chars(len);
1745                 if (len <= vec::len(ivals)) {
1746                     assert!((vec::len(res) == len));
1747                 }
1748                 assert!(vec::slice(ivals, 0u, vec::len(res)) ==
1749                              vec::map(res, |x| *x as int));
1750             }
1751         }
1752         let mut i = 0;
1753         while i < 8 {
1754             check_read_ln(i, wide_test, ivals);
1755             i += 1;
1756         }
1757         // check a long read for good measure
1758         check_read_ln(128, wide_test, ivals);
1759     }
1760
1761     #[test]
1762     fn test_readchar() {
1763         do io::with_str_reader(~"生") |inp| {
1764             let res : char = inp.read_char();
1765             assert!((res as int == 29983));
1766         }
1767     }
1768
1769     #[test]
1770     fn test_readchar_empty() {
1771         do io::with_str_reader(~"") |inp| {
1772             let res : char = inp.read_char();
1773             assert!((res as int == -1));
1774         }
1775     }
1776
1777     #[test]
1778     fn file_reader_not_exist() {
1779         match io::file_reader(&Path("not a file")) {
1780           result::Err(copy e) => {
1781             assert!(e == ~"error opening not a file");
1782           }
1783           result::Ok(_) => fail!()
1784         }
1785     }
1786
1787     #[test]
1788     #[should_fail]
1789     #[ignore(cfg(windows))]
1790     fn test_read_buffer_too_small() {
1791         let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
1792         // ensure the file exists
1793         io::file_writer(path, [io::Create]).get();
1794
1795         let file = io::file_reader(path).get();
1796         let mut buf = vec::from_elem(5, 0);
1797         file.read(buf, 6); // this should fail because buf is too small
1798     }
1799
1800     #[test]
1801     fn test_read_buffer_big_enough() {
1802         let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
1803         // ensure the file exists
1804         io::file_writer(path, [io::Create]).get();
1805
1806         let file = io::file_reader(path).get();
1807         let mut buf = vec::from_elem(5, 0);
1808         file.read(buf, 4); // this should succeed because buf is big enough
1809     }
1810
1811     #[test]
1812     fn test_write_empty() {
1813         let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
1814                                    [io::Create]).get();
1815         file.write([]);
1816     }
1817
1818     #[test]
1819     fn file_writer_bad_name() {
1820         match io::file_writer(&Path("?/?"), ~[]) {
1821           result::Err(copy e) => {
1822             assert!(str::starts_with(e, "error opening"));
1823           }
1824           result::Ok(_) => fail!()
1825         }
1826     }
1827
1828     #[test]
1829     fn buffered_file_writer_bad_name() {
1830         match io::buffered_file_writer(&Path("?/?")) {
1831           result::Err(copy e) => {
1832             assert!(str::starts_with(e, "error opening"));
1833           }
1834           result::Ok(_) => fail!()
1835         }
1836     }
1837
1838     #[test]
1839     fn bytes_buffer_overwrite() {
1840         let wr = BytesWriter();
1841         wr.write(~[0u8, 1u8, 2u8, 3u8]);
1842         assert!(wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
1843         wr.seek(-2, SeekCur);
1844         wr.write(~[4u8, 5u8, 6u8, 7u8]);
1845         assert!(wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
1846         wr.seek(-2, SeekEnd);
1847         wr.write(~[8u8]);
1848         wr.seek(1, SeekSet);
1849         wr.write(~[9u8]);
1850         assert!(wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
1851     }
1852
1853     #[test]
1854     fn test_read_write_le() {
1855         let path = Path("tmp/lib-io-test-read-write-le.tmp");
1856         let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1857
1858         // write the ints to the file
1859         {
1860             let file = io::file_writer(&path, [io::Create]).get();
1861             for uints.each |i| {
1862                 file.write_le_u64(*i);
1863             }
1864         }
1865
1866         // then read them back and check that they are the same
1867         {
1868             let file = io::file_reader(&path).get();
1869             for uints.each |i| {
1870                 assert!(file.read_le_u64() == *i);
1871             }
1872         }
1873     }
1874
1875     #[test]
1876     fn test_read_write_be() {
1877         let path = Path("tmp/lib-io-test-read-write-be.tmp");
1878         let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1879
1880         // write the ints to the file
1881         {
1882             let file = io::file_writer(&path, [io::Create]).get();
1883             for uints.each |i| {
1884                 file.write_be_u64(*i);
1885             }
1886         }
1887
1888         // then read them back and check that they are the same
1889         {
1890             let file = io::file_reader(&path).get();
1891             for uints.each |i| {
1892                 assert!(file.read_be_u64() == *i);
1893             }
1894         }
1895     }
1896
1897     #[test]
1898     fn test_read_be_int_n() {
1899         let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
1900         let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
1901
1902         // write the ints to the file
1903         {
1904             let file = io::file_writer(&path, [io::Create]).get();
1905             for ints.each |i| {
1906                 file.write_be_i32(*i);
1907             }
1908         }
1909
1910         // then read them back and check that they are the same
1911         {
1912             let file = io::file_reader(&path).get();
1913             for ints.each |i| {
1914                 // this tests that the sign extension is working
1915                 // (comparing the values as i32 would not test this)
1916                 assert!(file.read_be_int_n(4) == *i as i64);
1917             }
1918         }
1919     }
1920
1921     #[test]
1922     fn test_read_f32() {
1923         let path = Path("tmp/lib-io-test-read-f32.tmp");
1924         //big-endian floating-point 8.1250
1925         let buf = ~[0x41, 0x02, 0x00, 0x00];
1926
1927         {
1928             let file = io::file_writer(&path, [io::Create]).get();
1929             file.write(buf);
1930         }
1931
1932         {
1933             let file = io::file_reader(&path).get();
1934             let f = file.read_be_f32();
1935             assert!(f == 8.1250);
1936         }
1937     }
1938
1939 #[test]
1940     fn test_read_write_f32() {
1941         let path = Path("tmp/lib-io-test-read-write-f32.tmp");
1942         let f:f32 = 8.1250;
1943
1944         {
1945             let file = io::file_writer(&path, [io::Create]).get();
1946             file.write_be_f32(f);
1947             file.write_le_f32(f);
1948         }
1949
1950         {
1951             let file = io::file_reader(&path).get();
1952             assert!(file.read_be_f32() == 8.1250);
1953             assert!(file.read_le_f32() == 8.1250);
1954         }
1955     }
1956 }
1957
1958 //
1959 // Local Variables:
1960 // mode: rust
1961 // fill-column: 78;
1962 // indent-tabs-mode: nil
1963 // c-basic-offset: 4
1964 // buffer-file-coding-system: utf-8-unix
1965 // End:
1966 //