]> git.lizzy.rs Git - rust.git/blob - src/libcore/io.rs
4f9b8ccf7576cea0cecb298401b0b76ea753dc0a
[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 cmp::Eq;
20 use dvec::DVec;
21 use int;
22 use libc;
23 use libc::{c_int, c_long, c_uint, c_void, size_t, ssize_t};
24 use libc::consts::os::posix88::*;
25 use libc::consts::os::extra::*;
26 use option;
27 use os;
28 use prelude::*;
29 use ptr;
30 use result;
31 use str;
32 use uint;
33 use vec;
34
35 #[allow(non_camel_case_types)] // not sure what to do about this
36 pub type fd_t = c_int;
37
38 #[abi = "cdecl"]
39 extern mod rustrt {
40     unsafe fn rust_get_stdin() -> *libc::FILE;
41     unsafe fn rust_get_stdout() -> *libc::FILE;
42     unsafe fn rust_get_stderr() -> *libc::FILE;
43 }
44
45 // Reading
46
47 // FIXME (#2004): This is all buffered. We might need an unbuffered variant
48 // as well
49 pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
50
51
52 /// The raw underlying reader trait. All readers must implement this.
53 pub trait Reader {
54     // FIXME (#2004): Seekable really should be orthogonal.
55
56     /// Read up to len bytes (or EOF) and put them into bytes (which
57     /// must be at least len bytes long). Return number of bytes read.
58     // FIXME (#2982): This should probably return an error.
59     fn read(&self, bytes: &mut [u8], len: uint) -> uint;
60
61     /// Read a single byte, returning a negative value for EOF or read error.
62     fn read_byte(&self) -> int;
63
64     /// Return whether the stream is currently at EOF position.
65     fn eof(&self) -> bool;
66
67     /// Move the current position within the stream. The second parameter
68     /// determines the position that the first parameter is relative to.
69     fn seek(&self, position: int, style: SeekStyle);
70
71     /// Return the current position within the stream.
72     fn tell(&self) -> uint;
73 }
74
75 /// Generic utility functions defined on readers.
76 pub trait ReaderUtil {
77
78     /// Read len bytes into a new vec.
79     fn read_bytes(&self, len: uint) -> ~[u8];
80
81     /// Read up until the first '\n' char (which is not returned), or EOF.
82     fn read_line(&self) -> ~str;
83
84     /// Read n utf-8 encoded chars.
85     fn read_chars(&self, n: uint) -> ~[char];
86
87     /// Read a single utf-8 encoded char.
88     fn read_char(&self) -> char;
89
90     /// Read up until the first null byte (which is not returned), or EOF.
91     fn read_c_str(&self) -> ~str;
92
93     /// Read all the data remaining in the stream in one go.
94     fn read_whole_stream(&self) -> ~[u8];
95
96     /// Iterate over every byte until the iterator breaks or EOF.
97     fn each_byte(&self, it: fn(int) -> bool);
98
99     /// Iterate over every char until the iterator breaks or EOF.
100     fn each_char(&self, it: fn(char) -> bool);
101
102     /// Iterate over every line until the iterator breaks or EOF.
103     fn each_line(&self, it: fn(&str) -> bool);
104
105     /// Read n (between 1 and 8) little-endian unsigned integer bytes.
106     fn read_le_uint_n(&self, nbytes: uint) -> u64;
107
108     /// Read n (between 1 and 8) little-endian signed integer bytes.
109     fn read_le_int_n(&self, nbytes: uint) -> i64;
110
111     /// Read n (between 1 and 8) big-endian unsigned integer bytes.
112     fn read_be_uint_n(&self, nbytes: uint) -> u64;
113
114     /// Read n (between 1 and 8) big-endian signed integer bytes.
115     fn read_be_int_n(&self, nbytes: uint) -> i64;
116
117     /// Read a little-endian uint (number of bytes depends on system).
118     fn read_le_uint(&self) -> uint;
119
120     /// Read a little-endian int (number of bytes depends on system).
121     fn read_le_int(&self) -> int;
122
123     /// Read a big-endian uint (number of bytes depends on system).
124     fn read_be_uint(&self) -> uint;
125
126     /// Read a big-endian int (number of bytes depends on system).
127     fn read_be_int(&self) -> int;
128
129     /// Read a big-endian u64 (8 bytes).
130     fn read_be_u64(&self) -> u64;
131
132     /// Read a big-endian u32 (4 bytes).
133     fn read_be_u32(&self) -> u32;
134
135     /// Read a big-endian u16 (2 bytes).
136     fn read_be_u16(&self) -> u16;
137
138     /// Read a big-endian i64 (8 bytes).
139     fn read_be_i64(&self) -> i64;
140
141     /// Read a big-endian i32 (4 bytes).
142     fn read_be_i32(&self) -> i32;
143
144     /// Read a big-endian i16 (2 bytes).
145     fn read_be_i16(&self) -> i16;
146
147     /// Read a little-endian u64 (8 bytes).
148     fn read_le_u64(&self) -> u64;
149
150     /// Read a little-endian u32 (4 bytes).
151     fn read_le_u32(&self) -> u32;
152
153     /// Read a little-endian u16 (2 bytes).
154     fn read_le_u16(&self) -> u16;
155
156     /// Read a litle-endian i64 (8 bytes).
157     fn read_le_i64(&self) -> i64;
158
159     /// Read a litle-endian i32 (4 bytes).
160     fn read_le_i32(&self) -> i32;
161
162     /// Read a litle-endian i16 (2 bytes).
163     fn read_le_i16(&self) -> i16;
164
165     /// Read a u8 (1 byte).
166     fn read_u8(&self) -> u8;
167
168     /// Read a i8 (1 byte).
169     fn read_i8(&self) -> i8;
170 }
171
172 impl<T:Reader> ReaderUtil for T {
173
174     fn read_bytes(&self,len: uint) -> ~[u8] {
175         let mut bytes = vec::with_capacity(len);
176         unsafe { vec::raw::set_len(&mut bytes, len); }
177
178         let count = self.read(bytes, len);
179
180         unsafe { vec::raw::set_len(&mut bytes, count); }
181         bytes
182     }
183
184     fn read_line(&self) -> ~str {
185         let mut bytes = ~[];
186         loop {
187             let ch = self.read_byte();
188             if ch == -1 || ch == 10 { break; }
189             bytes.push(ch as u8);
190         }
191         str::from_bytes(bytes)
192     }
193
194     fn read_chars(&self, n: uint) -> ~[char] {
195         // returns the (consumed offset, n_req), appends characters to &chars
196         fn chars_from_bytes<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
197             -> (uint, uint) {
198             let mut i = 0;
199             let bytes_len = bytes.len();
200             while i < bytes_len {
201                 let b0 = bytes[i];
202                 let w = str::utf8_char_width(b0);
203                 let end = i + w;
204                 i += 1;
205                 assert (w > 0);
206                 if w == 1 {
207                     chars.push(b0 as char);
208                     loop;
209                 }
210                 // can't satisfy this char with the existing data
211                 if end > bytes_len {
212                     return (i - 1, end - bytes_len);
213                 }
214                 let mut val = 0;
215                 while i < end {
216                     let next = bytes[i] as int;
217                     i += 1;
218                     assert (next > -1);
219                     assert (next & 192 == 128);
220                     val <<= 6;
221                     val += (next & 63) as uint;
222                 }
223                 // See str::char_at
224                 val += ((b0 << ((w + 1) as u8)) as uint)
225                     << (w - 1) * 6 - w - 1u;
226                 chars.push(val as char);
227             }
228             return (i, 0);
229         }
230         let mut bytes = ~[];
231         let mut chars = ~[];
232         // might need more bytes, but reading n will never over-read
233         let mut nbread = n;
234         while nbread > 0 {
235             let data = self.read_bytes(nbread);
236             if data.is_empty() {
237                 // eof - FIXME (#2004): should we do something if
238                 // we're split in a unicode char?
239                 break;
240             }
241             bytes.push_all(data);
242             let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars);
243             let ncreq = n - chars.len();
244             // again we either know we need a certain number of bytes
245             // to complete a character, or we make sure we don't
246             // over-read by reading 1-byte per char needed
247             nbread = if ncreq > nbreq { ncreq } else { nbreq };
248             if nbread > 0 {
249                 bytes = vec::slice(bytes, offset, bytes.len()).to_vec();
250             }
251         }
252         chars
253     }
254
255     fn read_char(&self) -> char {
256         let c = self.read_chars(1);
257         if vec::len(c) == 0 {
258             return -1 as char; // FIXME will this stay valid? // #2004
259         }
260         assert(vec::len(c) == 1);
261         return c[0];
262     }
263
264     fn read_c_str(&self) -> ~str {
265         let mut bytes: ~[u8] = ~[];
266         loop {
267             let ch = self.read_byte();
268             if ch < 1 { break; } else { bytes.push(ch as u8); }
269         }
270         str::from_bytes(bytes)
271     }
272
273     fn read_whole_stream(&self) -> ~[u8] {
274         let mut bytes: ~[u8] = ~[];
275         while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
276         bytes
277     }
278
279     fn each_byte(&self, it: fn(int) -> bool) {
280         while !self.eof() {
281             if !it(self.read_byte()) { break; }
282         }
283     }
284
285     fn each_char(&self, it: fn(char) -> bool) {
286         while !self.eof() {
287             if !it(self.read_char()) { break; }
288         }
289     }
290
291     fn each_line(&self, it: fn(s: &str) -> bool) {
292         while !self.eof() {
293             if !it(self.read_line()) { break; }
294         }
295     }
296
297     // FIXME int reading methods need to deal with eof - issue #2004
298
299     fn read_le_uint_n(&self, nbytes: uint) -> u64 {
300         assert nbytes > 0 && nbytes <= 8;
301
302         let mut val = 0u64, pos = 0, i = nbytes;
303         while i > 0 {
304             val += (self.read_u8() as u64) << pos;
305             pos += 8;
306             i -= 1;
307         }
308         val
309     }
310
311     fn read_le_int_n(&self, nbytes: uint) -> i64 {
312         extend_sign(self.read_le_uint_n(nbytes), nbytes)
313     }
314
315     fn read_be_uint_n(&self, nbytes: uint) -> u64 {
316         assert nbytes > 0 && nbytes <= 8;
317
318         let mut val = 0u64, i = nbytes;
319         while i > 0 {
320             i -= 1;
321             val += (self.read_u8() as u64) << i * 8;
322         }
323         val
324     }
325
326     fn read_be_int_n(&self, nbytes: uint) -> i64 {
327         extend_sign(self.read_be_uint_n(nbytes), nbytes)
328     }
329
330     fn read_le_uint(&self) -> uint {
331         self.read_le_uint_n(uint::bytes) as uint
332     }
333
334     fn read_le_int(&self) -> int {
335         self.read_le_int_n(int::bytes) as int
336     }
337
338     fn read_be_uint(&self) -> uint {
339         self.read_be_uint_n(uint::bytes) as uint
340     }
341
342     fn read_be_int(&self) -> int {
343         self.read_be_int_n(int::bytes) as int
344     }
345
346     fn read_be_u64(&self) -> u64 {
347         self.read_be_uint_n(8) as u64
348     }
349
350     fn read_be_u32(&self) -> u32 {
351         self.read_be_uint_n(4) as u32
352     }
353
354     fn read_be_u16(&self) -> u16 {
355         self.read_be_uint_n(2) as u16
356     }
357
358     fn read_be_i64(&self) -> i64 {
359         self.read_be_int_n(8) as i64
360     }
361
362     fn read_be_i32(&self) -> i32 {
363         self.read_be_int_n(4) as i32
364     }
365
366     fn read_be_i16(&self) -> i16 {
367         self.read_be_int_n(2) as i16
368     }
369
370     fn read_le_u64(&self) -> u64 {
371         self.read_le_uint_n(8) as u64
372     }
373
374     fn read_le_u32(&self) -> u32 {
375         self.read_le_uint_n(4) as u32
376     }
377
378     fn read_le_u16(&self) -> u16 {
379         self.read_le_uint_n(2) as u16
380     }
381
382     fn read_le_i64(&self) -> i64 {
383         self.read_le_int_n(8) as i64
384     }
385
386     fn read_le_i32(&self) -> i32 {
387         self.read_le_int_n(4) as i32
388     }
389
390     fn read_le_i16(&self) -> i16 {
391         self.read_le_int_n(2) as i16
392     }
393
394     fn read_u8(&self) -> u8 {
395         self.read_byte() as u8
396     }
397
398     fn read_i8(&self) -> i8 {
399         self.read_byte() as i8
400     }
401 }
402
403 fn extend_sign(val: u64, nbytes: uint) -> i64 {
404     let shift = (8 - nbytes) * 8;
405     (val << shift) as i64 >> shift
406 }
407
408 // Reader implementations
409
410 fn convert_whence(whence: SeekStyle) -> i32 {
411     return match whence {
412       SeekSet => 0i32,
413       SeekCur => 1i32,
414       SeekEnd => 2i32
415     };
416 }
417
418 impl Reader for *libc::FILE {
419     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
420         unsafe {
421             do vec::as_mut_buf(bytes) |buf_p, buf_len| {
422                 assert buf_len >= len;
423
424                 let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
425                                         len as size_t, *self);
426
427                 count as uint
428             }
429         }
430     }
431     fn read_byte(&self) -> int {
432         unsafe {
433             libc::fgetc(*self) as int
434         }
435     }
436     fn eof(&self) -> bool {
437         unsafe {
438             return libc::feof(*self) != 0 as c_int;
439         }
440     }
441     fn seek(&self, offset: int, whence: SeekStyle) {
442         unsafe {
443             assert libc::fseek(*self,
444                                offset as c_long,
445                                convert_whence(whence)) == 0 as c_int;
446         }
447     }
448     fn tell(&self) -> uint {
449         unsafe {
450             return libc::ftell(*self) as uint;
451         }
452     }
453 }
454
455 struct Wrapper<T, C> {
456     base: T,
457     cleanup: C,
458 }
459
460 // A forwarding impl of reader that also holds on to a resource for the
461 // duration of its lifetime.
462 // FIXME there really should be a better way to do this // #2004
463 impl<R:Reader,C> Reader for Wrapper<R, C> {
464     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
465         self.base.read(bytes, len)
466     }
467     fn read_byte(&self) -> int { self.base.read_byte() }
468     fn eof(&self) -> bool { self.base.eof() }
469     fn seek(&self, off: int, whence: SeekStyle) {
470         self.base.seek(off, whence)
471     }
472     fn tell(&self) -> uint { self.base.tell() }
473 }
474
475 pub struct FILERes {
476     f: *libc::FILE,
477 }
478
479 impl Drop for FILERes {
480     fn finalize(&self) {
481         unsafe {
482             libc::fclose(self.f);
483         }
484     }
485 }
486
487 pub fn FILERes(f: *libc::FILE) -> FILERes {
488     FILERes {
489         f: f
490     }
491 }
492
493 pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
494     if cleanup {
495         @Wrapper { base: f, cleanup: FILERes(f) } as @Reader
496     } else {
497         @f as @Reader
498     }
499 }
500
501 // FIXME (#2004): this should either be an trait-less impl, a set of
502 // top-level functions that take a reader, or a set of default methods on
503 // reader (which can then be called reader)
504
505 pub fn stdin() -> @Reader {
506     unsafe {
507         @rustrt::rust_get_stdin() as @Reader
508     }
509 }
510
511 pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
512     unsafe {
513         let f = os::as_c_charp(path.to_str(), |pathbuf| {
514             os::as_c_charp("r", |modebuf|
515                 libc::fopen(pathbuf, modebuf)
516             )
517         });
518         return if f as uint == 0u { result::Err(~"error opening "
519                                                 + path.to_str()) }
520         else {
521             result::Ok(FILE_reader(f, true))
522         }
523     }
524 }
525
526
527 // Byte readers
528 pub struct BytesReader {
529     bytes: &[u8],
530     mut pos: uint
531 }
532
533 impl Reader for BytesReader {
534     fn read(&self, bytes: &mut [u8], len: uint) -> uint {
535         let count = uint::min(len, self.bytes.len() - self.pos);
536
537         let view = vec::slice(self.bytes, self.pos, self.bytes.len());
538         vec::bytes::copy_memory(bytes, view, count);
539
540         self.pos += count;
541
542         count
543     }
544     fn read_byte(&self) -> int {
545         if self.pos == self.bytes.len() { return -1; }
546         let b = self.bytes[self.pos];
547         self.pos += 1u;
548         return b as int;
549     }
550     fn eof(&self) -> bool { self.pos == self.bytes.len() }
551     fn seek(&self, offset: int, whence: SeekStyle) {
552         let pos = self.pos;
553         self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
554     }
555     fn tell(&self) -> uint { self.pos }
556 }
557
558 pub pure fn with_bytes_reader<t>(bytes: &[u8], f: fn(@Reader) -> t) -> t {
559     f(@BytesReader { bytes: bytes, pos: 0u } as @Reader)
560 }
561
562 pub pure fn with_str_reader<T>(s: &str, f: fn(@Reader) -> T) -> T {
563     str::byte_slice(s, |bytes| with_bytes_reader(bytes, f))
564 }
565
566 // Writing
567 pub enum FileFlag { Append, Create, Truncate, NoFlag, }
568
569 // What type of writer are we?
570 #[deriving_eq]
571 pub enum WriterType { Screen, File }
572
573 // FIXME (#2004): Seekable really should be orthogonal.
574 // FIXME (#2004): eventually u64
575 /// The raw underlying writer trait. All writers must implement this.
576 pub trait Writer {
577
578     /// Write all of the given bytes.
579     fn write(&self, v: &[const u8]);
580
581     /// Move the current position within the stream. The second parameter
582     /// determines the position that the first parameter is relative to.
583     fn seek(&self, int, SeekStyle);
584
585     /// Return the current position within the stream.
586     fn tell(&self) -> uint;
587
588     /// Flush the output buffer for this stream (if there is one).
589     fn flush(&self) -> int;
590
591     /// Determine if this Writer is writing to a file or not.
592     fn get_type(&self) -> WriterType;
593 }
594
595 impl<W:Writer,C> Writer for Wrapper<W, C> {
596     fn write(&self, bs: &[const u8]) { self.base.write(bs); }
597     fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
598     fn tell(&self) -> uint { self.base.tell() }
599     fn flush(&self) -> int { self.base.flush() }
600     fn get_type(&self) -> WriterType { File }
601 }
602
603 impl Writer for *libc::FILE {
604     fn write(&self, v: &[const u8]) {
605         unsafe {
606             do vec::as_const_buf(v) |vbuf, len| {
607                 let nout = libc::fwrite(vbuf as *c_void,
608                                         1,
609                                         len as size_t,
610                                         *self);
611                 if nout != len as size_t {
612                     error!("error writing buffer");
613                     log(error, os::last_os_error());
614                     fail!();
615                 }
616             }
617         }
618     }
619     fn seek(&self, offset: int, whence: SeekStyle) {
620         unsafe {
621             assert libc::fseek(*self,
622                                offset as c_long,
623                                convert_whence(whence)) == 0 as c_int;
624         }
625     }
626     fn tell(&self) -> uint {
627         unsafe {
628             libc::ftell(*self) as uint
629         }
630     }
631     fn flush(&self) -> int {
632         unsafe {
633             libc::fflush(*self) as int
634         }
635     }
636     fn get_type(&self) -> WriterType {
637         unsafe {
638             let fd = libc::fileno(*self);
639             if libc::isatty(fd) == 0 { File   }
640             else                     { Screen }
641         }
642     }
643 }
644
645 pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
646     if cleanup {
647         @Wrapper { base: f, cleanup: FILERes(f) } as @Writer
648     } else {
649         @f as @Writer
650     }
651 }
652
653 impl Writer for fd_t {
654     fn write(&self, v: &[const u8]) {
655         unsafe {
656             let mut count = 0u;
657             do vec::as_const_buf(v) |vbuf, len| {
658                 while count < len {
659                     let vb = ptr::const_offset(vbuf, count) as *c_void;
660                     let nout = libc::write(*self, vb, len as size_t);
661                     if nout < 0 as ssize_t {
662                         error!("error writing buffer");
663                         log(error, os::last_os_error());
664                         fail!();
665                     }
666                     count += nout as uint;
667                 }
668             }
669         }
670     }
671     fn seek(&self, _offset: int, _whence: SeekStyle) {
672         error!("need 64-bit foreign calls for seek, sorry");
673         fail!();
674     }
675     fn tell(&self) -> uint {
676         error!("need 64-bit foreign calls for tell, sorry");
677         fail!();
678     }
679     fn flush(&self) -> int { 0 }
680     fn get_type(&self) -> WriterType {
681         unsafe {
682             if libc::isatty(*self) == 0 { File } else { Screen }
683         }
684     }
685 }
686
687 pub struct FdRes {
688     fd: fd_t,
689 }
690
691 impl Drop for FdRes {
692     fn finalize(&self) {
693         unsafe {
694             libc::close(self.fd);
695         }
696     }
697 }
698
699 pub fn FdRes(fd: fd_t) -> FdRes {
700     FdRes {
701         fd: fd
702     }
703 }
704
705 pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
706     if cleanup {
707         @Wrapper { base: fd, cleanup: FdRes(fd) } as @Writer
708     } else {
709         @fd as @Writer
710     }
711 }
712
713
714 pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
715     -> Result<Writer, ~str> {
716
717     #[cfg(windows)]
718     fn wb() -> c_int { (O_WRONLY | O_BINARY) as c_int }
719
720     #[cfg(unix)]
721     fn wb() -> c_int { O_WRONLY as c_int }
722
723     let mut fflags: c_int = wb();
724     for vec::each(flags) |f| {
725         match *f {
726           Append => fflags |= O_APPEND as c_int,
727           Create => fflags |= O_CREAT as c_int,
728           Truncate => fflags |= O_TRUNC as c_int,
729           NoFlag => ()
730         }
731     }
732     let fd = unsafe {
733         do os::as_c_charp(path.to_str()) |pathbuf| {
734             libc::open(pathbuf, fflags,
735                        (S_IRUSR | S_IWUSR) as c_int)
736         }
737     };
738     if fd < (0 as c_int) {
739         result::Err(fmt!("error opening %s: %s", path.to_str(),
740                          os::last_os_error()))
741     } else {
742         result::Ok(fd_writer(fd, true))
743     }
744 }
745
746 pub fn u64_to_le_bytes<T>(n: u64, size: uint,
747                           f: fn(v: &[u8]) -> T) -> T {
748     assert size <= 8u;
749     match size {
750       1u => f(&[n as u8]),
751       2u => f(&[n as u8,
752               (n >> 8) as u8]),
753       4u => f(&[n as u8,
754               (n >> 8) as u8,
755               (n >> 16) as u8,
756               (n >> 24) as u8]),
757       8u => f(&[n as u8,
758               (n >> 8) as u8,
759               (n >> 16) as u8,
760               (n >> 24) as u8,
761               (n >> 32) as u8,
762               (n >> 40) as u8,
763               (n >> 48) as u8,
764               (n >> 56) as u8]),
765       _ => {
766
767         let mut bytes: ~[u8] = ~[], i = size, n = n;
768         while i > 0u {
769             bytes.push((n & 255_u64) as u8);
770             n >>= 8_u64;
771             i -= 1u;
772         }
773         f(bytes)
774       }
775     }
776 }
777
778 pub fn u64_to_be_bytes<T>(n: u64, size: uint,
779                            f: fn(v: &[u8]) -> T) -> T {
780     assert size <= 8u;
781     match size {
782       1u => f(&[n as u8]),
783       2u => f(&[(n >> 8) as u8,
784               n as u8]),
785       4u => f(&[(n >> 24) as u8,
786               (n >> 16) as u8,
787               (n >> 8) as u8,
788               n as u8]),
789       8u => f(&[(n >> 56) as u8,
790               (n >> 48) as u8,
791               (n >> 40) as u8,
792               (n >> 32) as u8,
793               (n >> 24) as u8,
794               (n >> 16) as u8,
795               (n >> 8) as u8,
796               n as u8]),
797       _ => {
798         let mut bytes: ~[u8] = ~[];
799         let mut i = size;
800         while i > 0u {
801             let shift = ((i - 1u) * 8u) as u64;
802             bytes.push((n >> shift) as u8);
803             i -= 1u;
804         }
805         f(bytes)
806       }
807     }
808 }
809
810 pub fn u64_from_be_bytes(data: &[const u8],
811                          start: uint, size: uint) -> u64 {
812     let mut sz = size;
813     assert (sz <= 8u);
814     let mut val = 0_u64;
815     let mut pos = start;
816     while sz > 0u {
817         sz -= 1u;
818         val += (data[pos] as u64) << ((sz * 8u) as u64);
819         pos += 1u;
820     }
821     return val;
822 }
823
824 // FIXME: #3048 combine trait+impl (or just move these to
825 // default methods on writer)
826 /// Generic utility functions defined on writers.
827 pub trait WriterUtil {
828
829     /// Write a single utf-8 encoded char.
830     fn write_char(&self, ch: char);
831
832     /// Write every char in the given str, encoded as utf-8.
833     fn write_str(&self, s: &str);
834
835     /// Write the given str, as utf-8, followed by '\n'.
836     fn write_line(&self, s: &str);
837
838     /// Write the result of passing n through `int::to_str_bytes`.
839     fn write_int(&self, n: int);
840
841     /// Write the result of passing n through `uint::to_str_bytes`.
842     fn write_uint(&self, n: uint);
843
844     /// Write a little-endian uint (number of bytes depends on system).
845     fn write_le_uint(&self, n: uint);
846
847     /// Write a little-endian int (number of bytes depends on system).
848     fn write_le_int(&self, n: int);
849
850     /// Write a big-endian uint (number of bytes depends on system).
851     fn write_be_uint(&self, n: uint);
852
853     /// Write a big-endian int (number of bytes depends on system).
854     fn write_be_int(&self, n: int);
855
856     /// Write a big-endian u64 (8 bytes).
857     fn write_be_u64(&self, n: u64);
858
859     /// Write a big-endian u32 (4 bytes).
860     fn write_be_u32(&self, n: u32);
861
862     /// Write a big-endian u16 (2 bytes).
863     fn write_be_u16(&self, n: u16);
864
865     /// Write a big-endian i64 (8 bytes).
866     fn write_be_i64(&self, n: i64);
867
868     /// Write a big-endian i32 (4 bytes).
869     fn write_be_i32(&self, n: i32);
870
871     /// Write a big-endian i16 (2 bytes).
872     fn write_be_i16(&self, n: i16);
873
874     /// Write a little-endian u64 (8 bytes).
875     fn write_le_u64(&self, n: u64);
876
877     /// Write a little-endian u32 (4 bytes).
878     fn write_le_u32(&self, n: u32);
879
880     /// Write a little-endian u16 (2 bytes).
881     fn write_le_u16(&self, n: u16);
882
883     /// Write a little-endian i64 (8 bytes).
884     fn write_le_i64(&self, n: i64);
885
886     /// Write a little-endian i32 (4 bytes).
887     fn write_le_i32(&self, n: i32);
888
889     /// Write a little-endian i16 (2 bytes).
890     fn write_le_i16(&self, n: i16);
891
892     /// Write a u8 (1 byte).
893     fn write_u8(&self, n: u8);
894
895     /// Write a i8 (1 byte).
896     fn write_i8(&self, n: i8);
897 }
898
899 impl<T:Writer> WriterUtil for T {
900     fn write_char(&self, ch: char) {
901         if ch as uint < 128u {
902             self.write(&[ch as u8]);
903         } else {
904             self.write_str(str::from_char(ch));
905         }
906     }
907     fn write_str(&self, s: &str) { str::byte_slice(s, |v| self.write(v)) }
908     fn write_line(&self, s: &str) {
909         self.write_str(s);
910         self.write_str(&"\n");
911     }
912     fn write_int(&self, n: int) {
913         int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
914     }
915     fn write_uint(&self, n: uint) {
916         uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
917     }
918     fn write_le_uint(&self, n: uint) {
919         u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
920     }
921     fn write_le_int(&self, n: int) {
922         u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
923     }
924     fn write_be_uint(&self, n: uint) {
925         u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
926     }
927     fn write_be_int(&self, n: int) {
928         u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
929     }
930     fn write_be_u64(&self, n: u64) {
931         u64_to_be_bytes(n, 8u, |v| self.write(v))
932     }
933     fn write_be_u32(&self, n: u32) {
934         u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
935     }
936     fn write_be_u16(&self, n: u16) {
937         u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
938     }
939     fn write_be_i64(&self, n: i64) {
940         u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
941     }
942     fn write_be_i32(&self, n: i32) {
943         u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
944     }
945     fn write_be_i16(&self, n: i16) {
946         u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
947     }
948     fn write_le_u64(&self, n: u64) {
949         u64_to_le_bytes(n, 8u, |v| self.write(v))
950     }
951     fn write_le_u32(&self, n: u32) {
952         u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
953     }
954     fn write_le_u16(&self, n: u16) {
955         u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
956     }
957     fn write_le_i64(&self, n: i64) {
958         u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
959     }
960     fn write_le_i32(&self, n: i32) {
961         u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
962     }
963     fn write_le_i16(&self, n: i16) {
964         u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
965     }
966
967     fn write_u8(&self, n: u8) { self.write([n]) }
968     fn write_i8(&self, n: i8) { self.write([n as u8]) }
969 }
970
971 #[allow(non_implicitly_copyable_typarams)]
972 pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<Writer, ~str> {
973     mk_file_writer(path, flags).chain(|w| result::Ok(w))
974 }
975
976
977 // FIXME: fileflags // #2004
978 pub fn buffered_file_writer(path: &Path) -> Result<Writer, ~str> {
979     unsafe {
980         let f = do os::as_c_charp(path.to_str()) |pathbuf| {
981             do os::as_c_charp("w") |modebuf| {
982                 libc::fopen(pathbuf, modebuf)
983             }
984         };
985         return if f as uint == 0u { result::Err(~"error opening "
986                                                 + path.to_str()) }
987         else { result::Ok(FILE_writer(f, true)) }
988     }
989 }
990
991 // FIXME (#2004) it would be great if this could be a const
992 // FIXME (#2004) why are these different from the way stdin() is
993 // implemented?
994 pub fn stdout() -> Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
995 pub fn stderr() -> Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
996
997 pub fn print(s: &str) { stdout().write_str(s); }
998 pub fn println(s: &str) { stdout().write_line(s); }
999
1000 pub struct BytesWriter {
1001     bytes: DVec<u8>,
1002     mut pos: uint,
1003 }
1004
1005 impl Writer for BytesWriter {
1006     fn write(&self, v: &[const u8]) {
1007         do self.bytes.swap |bytes| {
1008             let mut bytes = bytes;
1009             let v_len = v.len();
1010             let bytes_len = bytes.len();
1011
1012             let count = uint::max(bytes_len, self.pos + v_len);
1013             vec::reserve(&mut bytes, count);
1014             unsafe { vec::raw::set_len(&mut bytes, count); }
1015
1016             {
1017                 let view = vec::mut_slice(bytes, self.pos, count);
1018                 vec::bytes::copy_memory(view, v, v_len);
1019             }
1020
1021             self.pos += v_len;
1022
1023             bytes
1024         }
1025     }
1026     fn seek(&self, offset: int, whence: SeekStyle) {
1027         let pos = self.pos;
1028         let len = self.bytes.len();
1029         self.pos = seek_in_buf(offset, pos, len, whence);
1030     }
1031     fn tell(&self) -> uint { self.pos }
1032     fn flush(&self) -> int { 0 }
1033     fn get_type(&self) -> WriterType { File }
1034 }
1035
1036 pub pure fn BytesWriter() -> BytesWriter {
1037     BytesWriter { bytes: DVec(), mut pos: 0u }
1038 }
1039
1040 pub pure fn with_bytes_writer(f: fn(Writer)) -> ~[u8] {
1041     let wr = @BytesWriter();
1042     f(wr as Writer);
1043     // FIXME (#3758): This should not be needed.
1044     unsafe { wr.bytes.check_out(|bytes| bytes) }
1045 }
1046
1047 pub pure fn with_str_writer(f: fn(Writer)) -> ~str {
1048     let mut v = with_bytes_writer(f);
1049
1050     // FIXME (#3758): This should not be needed.
1051     unsafe {
1052         // Make sure the vector has a trailing null and is proper utf8.
1053         v.push(0);
1054     }
1055     assert str::is_utf8(v);
1056
1057     unsafe { ::cast::transmute(v) }
1058 }
1059
1060 // Utility functions
1061 pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
1062    uint {
1063     let mut bpos = pos as int;
1064     let blen = len as int;
1065     match whence {
1066       SeekSet => bpos = offset,
1067       SeekCur => bpos += offset,
1068       SeekEnd => bpos = blen + offset
1069     }
1070     if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
1071     return bpos as uint;
1072 }
1073
1074 #[allow(non_implicitly_copyable_typarams)]
1075 pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
1076     result::chain(read_whole_file(file), |bytes| {
1077         if str::is_utf8(bytes) {
1078             result::Ok(str::from_bytes(bytes))
1079        } else {
1080            result::Err(file.to_str() + ~" is not UTF-8")
1081        }
1082     })
1083 }
1084
1085 // FIXME (#2004): implement this in a low-level way. Going through the
1086 // abstractions is pointless.
1087 #[allow(non_implicitly_copyable_typarams)]
1088 pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
1089     result::chain(file_reader(file), |rdr| {
1090         result::Ok(rdr.read_whole_stream())
1091     })
1092 }
1093
1094 // fsync related
1095
1096 pub mod fsync {
1097     use prelude::*;
1098     use io::{FILERes, FdRes, fd_t};
1099     use libc;
1100     use os;
1101
1102     pub enum Level {
1103         // whatever fsync does on that platform
1104         FSync,
1105
1106         // fdatasync on linux, similiar or more on other platforms
1107         FDataSync,
1108
1109         // full fsync
1110         //
1111         // You must additionally sync the parent directory as well!
1112         FullFSync,
1113     }
1114
1115
1116     // Artifacts that need to fsync on destruction
1117     pub struct Res<t> {
1118         arg: Arg<t>,
1119     }
1120
1121     impl<T:Copy> Drop for Res<T> {
1122         fn finalize(&self) {
1123           match self.arg.opt_level {
1124             None => (),
1125             Some(level) => {
1126               // fail hard if not succesful
1127               assert((self.arg.fsync_fn)(self.arg.val, level) != -1);
1128             }
1129           }
1130         }
1131     }
1132
1133     pub fn Res<t: Copy>(arg: Arg<t>) -> Res<t>{
1134         Res {
1135             arg: arg
1136         }
1137     }
1138
1139     pub struct Arg<t> {
1140         val: t,
1141         opt_level: Option<Level>,
1142         fsync_fn: @fn(f: t, Level) -> int,
1143     }
1144
1145     // fsync file after executing blk
1146     // FIXME (#2004) find better way to create resources within lifetime of
1147     // outer res
1148     pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
1149                          blk: fn(v: Res<*libc::FILE>)) {
1150         unsafe {
1151             blk(Res(Arg {
1152                 val: file.f, opt_level: opt_level,
1153                 fsync_fn: |file, l| {
1154                     unsafe {
1155                         os::fsync_fd(libc::fileno(file), l) as int
1156                     }
1157                 }
1158             }));
1159         }
1160     }
1161
1162     // fsync fd after executing blk
1163     pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
1164                        blk: fn(v: Res<fd_t>)) {
1165         blk(Res(Arg {
1166             val: fd.fd, opt_level: opt_level,
1167             fsync_fn: |fd, l| os::fsync_fd(fd, l) as int
1168         }));
1169     }
1170
1171     // Type of objects that may want to fsync
1172     pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
1173
1174     // Call o.fsync after executing blk
1175     pub fn obj_sync(o: FSyncable, opt_level: Option<Level>,
1176                     blk: fn(v: Res<FSyncable>)) {
1177         blk(Res(Arg {
1178             val: o, opt_level: opt_level,
1179             fsync_fn: |o, l| o.fsync(l)
1180         }));
1181     }
1182 }
1183
1184 #[cfg(test)]
1185 mod tests {
1186     use debug;
1187     use i32;
1188     use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
1189     use io;
1190     use path::Path;
1191     use result;
1192     use str;
1193     use u64;
1194     use vec;
1195
1196     #[test]
1197     fn test_simple() {
1198         let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
1199         log(debug, tmpfile);
1200         let frood: ~str =
1201             ~"A hoopy frood who really knows where his towel is.";
1202         log(debug, copy frood);
1203         {
1204             let out: io::Writer =
1205                 result::get(
1206                     &io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
1207             out.write_str(frood);
1208         }
1209         let inp: io::Reader = result::get(&io::file_reader(tmpfile));
1210         let frood2: ~str = inp.read_c_str();
1211         log(debug, copy frood2);
1212         assert frood == frood2;
1213     }
1214
1215     #[test]
1216     fn test_readchars_empty() {
1217         do io::with_str_reader(~"") |inp| {
1218             let res : ~[char] = inp.read_chars(128);
1219             assert(vec::len(res) == 0);
1220         }
1221     }
1222
1223     #[test]
1224     fn test_read_line_utf8() {
1225         do io::with_str_reader(~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
1226             let line = inp.read_line();
1227             assert line == ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1228         }
1229     }
1230
1231     #[test]
1232     fn test_readchars_wide() {
1233         let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
1234         let ivals : ~[int] = ~[
1235             29983, 38152, 30340, 27748,
1236             21273, 20999, 32905, 27748,
1237             104, 101, 108, 108, 111,
1238             29983, 38152, 30340, 27748,
1239             21273, 20999, 32905, 27748];
1240         fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
1241             do io::with_str_reader(s) |inp| {
1242                 let res : ~[char] = inp.read_chars(len);
1243                 if (len <= vec::len(ivals)) {
1244                     assert(vec::len(res) == len);
1245                 }
1246                 assert(vec::slice(ivals, 0u, vec::len(res)) ==
1247                        vec::map(res, |x| *x as int));
1248             }
1249         }
1250         let mut i = 0;
1251         while i < 8 {
1252             check_read_ln(i, wide_test, ivals);
1253             i += 1;
1254         }
1255         // check a long read for good measure
1256         check_read_ln(128, wide_test, ivals);
1257     }
1258
1259     #[test]
1260     fn test_readchar() {
1261         do io::with_str_reader(~"生") |inp| {
1262             let res : char = inp.read_char();
1263             assert(res as int == 29983);
1264         }
1265     }
1266
1267     #[test]
1268     fn test_readchar_empty() {
1269         do io::with_str_reader(~"") |inp| {
1270             let res : char = inp.read_char();
1271             assert(res as int == -1);
1272         }
1273     }
1274
1275     #[test]
1276     fn file_reader_not_exist() {
1277         match io::file_reader(&Path("not a file")) {
1278           result::Err(copy e) => {
1279             assert e == ~"error opening not a file";
1280           }
1281           result::Ok(_) => fail!()
1282         }
1283     }
1284
1285     #[test]
1286     #[should_fail]
1287     #[ignore(cfg(windows))]
1288     fn test_read_buffer_too_small() {
1289         let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
1290         // ensure the file exists
1291         io::file_writer(path, [io::Create]).get();
1292
1293         let file = io::file_reader(path).get();
1294         let mut buf = vec::from_elem(5, 0);
1295         file.read(buf, 6); // this should fail because buf is too small
1296     }
1297
1298     #[test]
1299     fn test_read_buffer_big_enough() {
1300         let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
1301         // ensure the file exists
1302         io::file_writer(path, [io::Create]).get();
1303
1304         let file = io::file_reader(path).get();
1305         let mut buf = vec::from_elem(5, 0);
1306         file.read(buf, 4); // this should succeed because buf is big enough
1307     }
1308
1309     #[test]
1310     fn test_write_empty() {
1311         let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
1312                                    [io::Create]).get();
1313         file.write([]);
1314     }
1315
1316     #[test]
1317     fn file_writer_bad_name() {
1318         match io::file_writer(&Path("?/?"), ~[]) {
1319           result::Err(copy e) => {
1320             assert str::starts_with(e, "error opening");
1321           }
1322           result::Ok(_) => fail!()
1323         }
1324     }
1325
1326     #[test]
1327     fn buffered_file_writer_bad_name() {
1328         match io::buffered_file_writer(&Path("?/?")) {
1329           result::Err(copy e) => {
1330             assert str::starts_with(e, "error opening");
1331           }
1332           result::Ok(_) => fail!()
1333         }
1334     }
1335
1336     #[test]
1337     fn bytes_buffer_overwrite() {
1338         let wr = BytesWriter();
1339         wr.write(~[0u8, 1u8, 2u8, 3u8]);
1340         assert wr.bytes.borrow(|bytes| bytes == ~[0u8, 1u8, 2u8, 3u8]);
1341         wr.seek(-2, SeekCur);
1342         wr.write(~[4u8, 5u8, 6u8, 7u8]);
1343         assert wr.bytes.borrow(|bytes| bytes ==
1344             ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
1345         wr.seek(-2, SeekEnd);
1346         wr.write(~[8u8]);
1347         wr.seek(1, SeekSet);
1348         wr.write(~[9u8]);
1349         assert wr.bytes.borrow(|bytes| bytes ==
1350             ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
1351     }
1352
1353     #[test]
1354     fn test_read_write_le() {
1355         let path = Path("tmp/lib-io-test-read-write-le.tmp");
1356         let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1357
1358         // write the ints to the file
1359         {
1360             let file = io::file_writer(&path, [io::Create]).get();
1361             for uints.each |i| {
1362                 file.write_le_u64(*i);
1363             }
1364         }
1365
1366         // then read them back and check that they are the same
1367         {
1368             let file = io::file_reader(&path).get();
1369             for uints.each |i| {
1370                 assert file.read_le_u64() == *i;
1371             }
1372         }
1373     }
1374
1375     #[test]
1376     fn test_read_write_be() {
1377         let path = Path("tmp/lib-io-test-read-write-be.tmp");
1378         let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
1379
1380         // write the ints to the file
1381         {
1382             let file = io::file_writer(&path, [io::Create]).get();
1383             for uints.each |i| {
1384                 file.write_be_u64(*i);
1385             }
1386         }
1387
1388         // then read them back and check that they are the same
1389         {
1390             let file = io::file_reader(&path).get();
1391             for uints.each |i| {
1392                 assert file.read_be_u64() == *i;
1393             }
1394         }
1395     }
1396
1397     #[test]
1398     fn test_read_be_int_n() {
1399         let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
1400         let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
1401
1402         // write the ints to the file
1403         {
1404             let file = io::file_writer(&path, [io::Create]).get();
1405             for ints.each |i| {
1406                 file.write_be_i32(*i);
1407             }
1408         }
1409
1410         // then read them back and check that they are the same
1411         {
1412             let file = io::file_reader(&path).get();
1413             for ints.each |i| {
1414                 // this tests that the sign extension is working
1415                 // (comparing the values as i32 would not test this)
1416                 assert file.read_be_int_n(4) == *i as i64;
1417             }
1418         }
1419     }
1420
1421 }
1422
1423 //
1424 // Local Variables:
1425 // mode: rust
1426 // fill-column: 78;
1427 // indent-tabs-mode: nil
1428 // c-basic-offset: 4
1429 // buffer-file-coding-system: utf-8-unix
1430 // End:
1431 //