2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
2011-12-06 15:58:45 -06:00
|
|
|
|
2013-05-19 20:59:21 -05:00
|
|
|
The `io` module contains basic input and output routines.
|
|
|
|
|
|
|
|
A quick summary:
|
|
|
|
|
|
|
|
## `Reader` and `Writer` traits
|
|
|
|
|
2013-05-19 21:39:02 -05:00
|
|
|
These traits define the minimal set of methods that anything that can do
|
2013-05-19 20:59:21 -05:00
|
|
|
input and output should implement.
|
|
|
|
|
|
|
|
## `ReaderUtil` and `WriterUtil` traits
|
|
|
|
|
|
|
|
Richer methods that allow you to do more. `Reader` only lets you read a certain
|
2013-05-19 21:39:02 -05:00
|
|
|
number of bytes into a buffer, while `ReaderUtil` allows you to read a whole
|
2013-05-19 20:59:21 -05:00
|
|
|
line, for example.
|
|
|
|
|
|
|
|
Generally, these richer methods are probably the ones you want to actually
|
|
|
|
use in day-to-day Rust.
|
|
|
|
|
|
|
|
Furthermore, because there is an implementation of `ReaderUtil` for
|
|
|
|
`<T: Reader>`, when your input or output code implements `Reader`, you get
|
|
|
|
all of these methods for free.
|
|
|
|
|
|
|
|
## `print` and `println`
|
|
|
|
|
|
|
|
These very useful functions are defined here. You generally don't need to
|
|
|
|
import them, though, as the prelude already does.
|
|
|
|
|
|
|
|
## `stdin`, `stdout`, and `stderr`
|
|
|
|
|
|
|
|
These functions return references to the classic three file descriptors. They
|
|
|
|
implement `Reader` and `Writer`, where appropriate.
|
2012-09-19 18:52:32 -05:00
|
|
|
|
2011-12-06 15:58:45 -06:00
|
|
|
*/
|
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
#[allow(missing_doc)];
|
|
|
|
|
2013-07-24 22:23:38 -05:00
|
|
|
use cast;
|
2013-09-03 18:24:12 -05:00
|
|
|
use cast::transmute;
|
2013-07-02 14:47:32 -05:00
|
|
|
use clone::Clone;
|
2013-08-03 19:13:14 -05:00
|
|
|
use c_str::ToCStr;
|
2013-05-12 19:34:15 -05:00
|
|
|
use container::Container;
|
2012-12-23 16:41:37 -06:00
|
|
|
use int;
|
2013-09-08 10:01:16 -05:00
|
|
|
use iter::Iterator;
|
2012-09-04 13:12:17 -05:00
|
|
|
use libc::consts::os::posix88::*;
|
2013-08-12 01:06:06 -05:00
|
|
|
use libc::{c_int, c_void, size_t};
|
2013-07-24 22:23:38 -05:00
|
|
|
use libc;
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
use num;
|
2013-07-24 22:23:38 -05:00
|
|
|
use ops::Drop;
|
2013-08-01 02:16:42 -05:00
|
|
|
use option::{Some, None};
|
2012-12-23 16:41:37 -06:00
|
|
|
use os;
|
2013-09-26 19:21:59 -05:00
|
|
|
use path::{Path,GenericPath};
|
2012-12-23 16:41:37 -06:00
|
|
|
use ptr;
|
2013-07-24 22:23:38 -05:00
|
|
|
use result::{Result, Ok, Err};
|
2013-07-22 23:41:46 -05:00
|
|
|
use str::{StrSlice, OwnedStr};
|
2013-07-24 22:23:38 -05:00
|
|
|
use str;
|
2013-10-06 20:51:49 -05:00
|
|
|
use to_str::ToStr;
|
2012-12-23 16:41:37 -06:00
|
|
|
use uint;
|
2013-06-27 04:48:50 -05:00
|
|
|
use vec::{MutableVector, ImmutableVector, OwnedVector, OwnedCopyableVector, CopyableVector};
|
2013-07-24 22:23:38 -05:00
|
|
|
use vec;
|
2012-03-12 22:04:27 -05:00
|
|
|
|
2012-08-14 15:38:35 -05:00
|
|
|
#[allow(non_camel_case_types)] // not sure what to do about this
|
2013-01-08 21:37:25 -06:00
|
|
|
pub type fd_t = c_int;
|
2011-07-10 14:47:51 -05:00
|
|
|
|
2013-03-05 13:57:50 -06:00
|
|
|
pub mod rustrt {
|
|
|
|
use libc;
|
|
|
|
|
|
|
|
#[link_name = "rustrt"]
|
2013-10-14 07:33:05 -05:00
|
|
|
extern {
|
2013-08-02 16:30:00 -05:00
|
|
|
pub fn rust_get_stdin() -> *libc::FILE;
|
|
|
|
pub fn rust_get_stdout() -> *libc::FILE;
|
|
|
|
pub fn rust_get_stderr() -> *libc::FILE;
|
2013-03-05 13:57:50 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reading
|
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004): This is all buffered. We might need an unbuffered variant
|
|
|
|
// as well
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
|
|
|
* The SeekStyle enum describes the relationship between the position
|
|
|
|
* we'd like to seek to from our current position. It's used as an argument
|
|
|
|
* to the `seek` method defined on the `Reader` trait.
|
|
|
|
*
|
|
|
|
* There are three seek styles:
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* 1. `SeekSet` means that the new position should become our position.
|
|
|
|
* 2. `SeekCur` means that we should seek from the current position.
|
|
|
|
* 3. `SeekEnd` means that we should seek from the end.
|
|
|
|
*
|
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-10-01 16:02:10 -05:00
|
|
|
pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
|
2011-07-10 14:47:51 -05:00
|
|
|
|
|
|
|
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
|
|
|
* The core Reader trait. All readers must implement this trait.
|
|
|
|
*
|
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-10-01 16:02:10 -05:00
|
|
|
pub trait Reader {
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004): Seekable really should be orthogonal.
|
2012-07-20 23:49:20 -05:00
|
|
|
|
|
|
|
// FIXME (#2982): This should probably return an error.
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
2013-05-19 14:57:00 -05:00
|
|
|
* Reads bytes and puts them into `bytes`, advancing the cursor. Returns the
|
|
|
|
* number of bytes read.
|
2013-04-01 18:37:40 -05:00
|
|
|
*
|
2013-04-02 19:29:02 -05:00
|
|
|
* The number of bytes to be read is `len` or the end of the file,
|
2013-04-01 18:37:40 -05:00
|
|
|
* whichever comes first.
|
|
|
|
*
|
|
|
|
* The buffer must be at least `len` bytes long.
|
|
|
|
*
|
2013-05-19 23:40:13 -05:00
|
|
|
* `read` is conceptually similar to C's `fread` function.
|
2013-05-19 14:57:00 -05:00
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2013-02-11 22:18:34 -06:00
|
|
|
fn read(&self, bytes: &mut [u8], len: uint) -> uint;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
2013-05-19 14:57:00 -05:00
|
|
|
* Reads a single byte, advancing the cursor.
|
2013-04-01 18:37:40 -05:00
|
|
|
*
|
|
|
|
* In the case of an EOF or an error, returns a negative value.
|
|
|
|
*
|
2013-05-19 14:57:00 -05:00
|
|
|
* `read_byte` is conceptually similar to C's `getc` function.
|
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_byte(&self) -> int;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
|
|
|
* Returns a boolean value: are we currently at EOF?
|
|
|
|
*
|
2013-07-28 07:53:00 -05:00
|
|
|
* Note that stream position may be already at the end-of-file point,
|
|
|
|
* but `eof` returns false until an attempt to read at that position.
|
|
|
|
*
|
2013-05-19 14:57:00 -05:00
|
|
|
* `eof` is conceptually similar to C's `feof` function.
|
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn eof(&self) -> bool;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
|
|
|
* Seek to a given `position` in the stream.
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* Takes an optional SeekStyle, which affects how we seek from the
|
|
|
|
* position. See `SeekStyle` docs for more details.
|
|
|
|
*
|
2013-05-19 23:40:13 -05:00
|
|
|
* `seek` is conceptually similar to C's `fseek` function.
|
2013-05-19 14:57:00 -05:00
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, position: int, style: SeekStyle);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 18:37:40 -05:00
|
|
|
/**
|
|
|
|
* Returns the current position within the stream.
|
|
|
|
*
|
2013-05-19 14:57:00 -05:00
|
|
|
* `tell` is conceptually similar to C's `ftell` function.
|
|
|
|
*
|
2013-04-01 18:37:40 -05:00
|
|
|
* # Examples
|
2013-04-02 19:29:02 -05:00
|
|
|
*
|
|
|
|
* None right now.
|
2013-04-01 18:37:40 -05:00
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn tell(&self) -> uint;
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 16:49:50 -06:00
|
|
|
impl Reader for @Reader {
|
|
|
|
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
|
|
|
self.read(bytes, len)
|
|
|
|
}
|
|
|
|
fn read_byte(&self) -> int {
|
|
|
|
self.read_byte()
|
|
|
|
}
|
|
|
|
fn eof(&self) -> bool {
|
|
|
|
self.eof()
|
|
|
|
}
|
|
|
|
fn seek(&self, position: int, style: SeekStyle) {
|
|
|
|
self.seek(position, style)
|
|
|
|
}
|
|
|
|
fn tell(&self) -> uint {
|
|
|
|
self.tell()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* The `ReaderUtil` trait is a home for many of the utility functions
|
|
|
|
* a particular Reader should implement.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
|
|
|
|
* on higher-level concepts like 'chars' and 'lines.'
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples:
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-10-01 16:02:10 -05:00
|
|
|
pub trait ReaderUtil {
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `len` number of bytes, and gives you a new vector back.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_bytes(&self, len: uint) -> ~[u8];
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
2013-04-18 08:36:38 -05:00
|
|
|
* Reads up until a specific byte is seen or EOF.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The `include` parameter specifies if the character should be included
|
|
|
|
* in the returned string.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-04-18 08:36:38 -05:00
|
|
|
fn read_until(&self, c: u8, include: bool) -> ~str;
|
2013-03-03 04:03:30 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads up until the first '\n' or EOF.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The '\n' is not included in the result.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_line(&self) -> ~str;
|
2012-09-25 12:16:43 -05:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `n` chars.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* Assumes that those chars are UTF-8 encoded.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The '\n' is not included in the result.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_chars(&self, n: uint) -> ~[char];
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a single UTF-8 encoded char.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_char(&self) -> char;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads up until the first null byte or EOF.
|
|
|
|
*
|
|
|
|
* The null byte is not returned.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_c_str(&self) -> ~str;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads all remaining data in the stream.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_whole_stream(&self) -> ~[u8];
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Iterate over every byte until EOF or the iterator breaks.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_byte(&self, it: &fn(int) -> bool) -> bool;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Iterate over every char until EOF or the iterator breaks.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_char(&self, it: &fn(char) -> bool) -> bool;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Iterate over every line until EOF or the iterator breaks.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_line(&self, it: &fn(&str) -> bool) -> bool;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads all of the lines in the stream.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* Returns a vector of those lines.
|
|
|
|
*
|
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-03-14 01:41:28 -05:00
|
|
|
fn read_lines(&self) -> ~[~str];
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `n` little-endian unsigned integer bytes.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `n` must be between 1 and 8, inclusive.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_uint_n(&self, nbytes: uint) -> u64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `n` little-endian signed integer bytes.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `n` must be between 1 and 8, inclusive.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_int_n(&self, nbytes: uint) -> i64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `n` big-endian unsigned integer bytes.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `n` must be between 1 and 8, inclusive.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_uint_n(&self, nbytes: uint) -> u64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads `n` big-endian signed integer bytes.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `n` must be between 1 and 8, inclusive.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_int_n(&self, nbytes: uint) -> i64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian unsigned integer.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The number of bytes returned is system-dependant.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_uint(&self) -> uint;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian integer.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The number of bytes returned is system-dependant.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_int(&self) -> int;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian unsigned integer.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The number of bytes returned is system-dependant.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_uint(&self) -> uint;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian integer.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* The number of bytes returned is system-dependant.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_int(&self) -> int;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `u64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u64`s are 8 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u64(&self) -> u64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `u32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u32`s are 4 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u32(&self) -> u32;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `u16`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u16`s are 2 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u16(&self) -> u16;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `i64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i64`s are 8 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i64(&self) -> i64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `i32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i32`s are 4 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i32(&self) -> i32;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `i16`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i16`s are 2 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i16(&self) -> i16;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `f64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_be_f64(&self) -> f64;
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a big-endian `f32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_be_f32(&self) -> f32;
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `u64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u64`s are 8 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u64(&self) -> u64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `u32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u32`s are 4 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u32(&self) -> u32;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `u16`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u16`s are 2 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u16(&self) -> u16;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `i64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i64`s are 8 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i64(&self) -> i64;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `i32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i32`s are 4 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i32(&self) -> i32;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `i16`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `i16`s are 2 bytes long.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i16(&self) -> i16;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `f64`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_le_f64(&self) -> f64;
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
|
|
|
* Reads a little-endian `f32`.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_le_f32(&self) -> f32;
|
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
2013-04-02 19:31:42 -05:00
|
|
|
* Read a u8.
|
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* `u8`s are 1 byte.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_u8(&self) -> u8;
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-01 20:03:54 -05:00
|
|
|
/**
|
2013-04-02 19:31:42 -05:00
|
|
|
* Read an i8.
|
|
|
|
*
|
2013-04-01 20:20:30 -05:00
|
|
|
* `i8`s are 1 byte.
|
2013-04-02 19:31:42 -05:00
|
|
|
*
|
2013-04-01 20:03:54 -05:00
|
|
|
* # Examples
|
|
|
|
*
|
|
|
|
* None right now.
|
|
|
|
*/
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_i8(&self) -> i8;
|
2012-08-25 20:42:36 -05:00
|
|
|
}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<T:Reader> ReaderUtil for T {
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-08-30 05:53:05 -05:00
|
|
|
fn read_bytes(&self, len: uint) -> ~[u8] {
|
2012-10-18 11:10:37 -05:00
|
|
|
let mut bytes = vec::with_capacity(len);
|
|
|
|
unsafe { vec::raw::set_len(&mut bytes, len); }
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2012-10-18 11:10:37 -05:00
|
|
|
let count = self.read(bytes, len);
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2012-10-18 11:10:37 -05:00
|
|
|
unsafe { vec::raw::set_len(&mut bytes, count); }
|
2013-02-15 02:51:28 -06:00
|
|
|
bytes
|
2012-07-20 23:49:20 -05:00
|
|
|
}
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-04-18 08:36:38 -05:00
|
|
|
fn read_until(&self, c: u8, include: bool) -> ~str {
|
2013-01-28 21:32:02 -06:00
|
|
|
let mut bytes = ~[];
|
2012-08-25 20:42:36 -05:00
|
|
|
loop {
|
|
|
|
let ch = self.read_byte();
|
2013-03-03 04:03:30 -06:00
|
|
|
if ch == -1 || ch == c as int {
|
2013-03-14 01:41:28 -05:00
|
|
|
if include && ch == c as int {
|
|
|
|
bytes.push(ch as u8);
|
|
|
|
}
|
2013-03-03 04:03:30 -06:00
|
|
|
break;
|
|
|
|
}
|
2013-01-28 21:32:02 -06:00
|
|
|
bytes.push(ch as u8);
|
2012-08-25 20:42:36 -05:00
|
|
|
}
|
2013-09-05 07:17:24 -05:00
|
|
|
str::from_utf8(bytes)
|
2012-08-25 20:42:36 -05:00
|
|
|
}
|
|
|
|
|
2013-03-03 04:03:30 -06:00
|
|
|
fn read_line(&self) -> ~str {
|
2013-04-18 08:36:38 -05:00
|
|
|
self.read_until('\n' as u8, false)
|
2013-03-03 04:03:30 -06:00
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_chars(&self, n: uint) -> ~[char] {
|
2012-01-08 10:37:03 -06:00
|
|
|
// returns the (consumed offset, n_req), appends characters to &chars
|
2013-09-05 07:17:24 -05:00
|
|
|
fn chars_from_utf8<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
|
2012-09-26 12:13:43 -05:00
|
|
|
-> (uint, uint) {
|
|
|
|
let mut i = 0;
|
2012-10-18 11:10:37 -05:00
|
|
|
let bytes_len = bytes.len();
|
|
|
|
while i < bytes_len {
|
|
|
|
let b0 = bytes[i];
|
2012-01-08 10:37:03 -06:00
|
|
|
let w = str::utf8_char_width(b0);
|
|
|
|
let end = i + w;
|
2012-09-26 12:13:43 -05:00
|
|
|
i += 1;
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((w > 0));
|
2012-09-26 12:13:43 -05:00
|
|
|
if w == 1 {
|
2013-09-03 18:24:12 -05:00
|
|
|
unsafe {
|
|
|
|
chars.push(transmute(b0 as u32));
|
|
|
|
}
|
2013-10-01 16:31:03 -05:00
|
|
|
continue;
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
|
|
|
// can't satisfy this char with the existing data
|
2012-10-18 11:10:37 -05:00
|
|
|
if end > bytes_len {
|
|
|
|
return (i - 1, end - bytes_len);
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
2012-09-26 12:13:43 -05:00
|
|
|
let mut val = 0;
|
2012-01-08 10:37:03 -06:00
|
|
|
while i < end {
|
2012-10-18 11:10:37 -05:00
|
|
|
let next = bytes[i] as int;
|
2012-09-26 12:13:43 -05:00
|
|
|
i += 1;
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((next > -1));
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(next & 192, 128);
|
2012-09-26 12:13:43 -05:00
|
|
|
val <<= 6;
|
2012-02-09 04:50:54 -06:00
|
|
|
val += (next & 63) as uint;
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
2013-06-10 06:46:36 -05:00
|
|
|
// See str::StrSlice::char_at
|
2012-09-26 12:13:43 -05:00
|
|
|
val += ((b0 << ((w + 1) as u8)) as uint)
|
|
|
|
<< (w - 1) * 6 - w - 1u;
|
2013-09-03 18:24:12 -05:00
|
|
|
unsafe {
|
|
|
|
chars.push(transmute(val as u32));
|
|
|
|
}
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
2012-09-26 12:13:43 -05:00
|
|
|
return (i, 0);
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
2012-10-18 11:14:11 -05:00
|
|
|
let mut bytes = ~[];
|
|
|
|
let mut chars = ~[];
|
2012-01-09 06:49:17 -06:00
|
|
|
// might need more bytes, but reading n will never over-read
|
2012-03-12 22:04:27 -05:00
|
|
|
let mut nbread = n;
|
2012-09-26 12:13:43 -05:00
|
|
|
while nbread > 0 {
|
2012-01-09 06:49:17 -06:00
|
|
|
let data = self.read_bytes(nbread);
|
2012-09-26 12:13:43 -05:00
|
|
|
if data.is_empty() {
|
2012-06-21 18:44:10 -05:00
|
|
|
// eof - FIXME (#2004): should we do something if
|
|
|
|
// we're split in a unicode char?
|
2012-01-08 10:37:03 -06:00
|
|
|
break;
|
|
|
|
}
|
2012-10-18 11:10:37 -05:00
|
|
|
bytes.push_all(data);
|
2013-09-05 07:17:24 -05:00
|
|
|
let (offset, nbreq) = chars_from_utf8::<T>(&bytes, &mut chars);
|
2012-09-26 12:13:43 -05:00
|
|
|
let ncreq = n - chars.len();
|
2012-01-09 06:49:17 -06:00
|
|
|
// again we either know we need a certain number of bytes
|
|
|
|
// to complete a character, or we make sure we don't
|
|
|
|
// over-read by reading 1-byte per char needed
|
2012-01-08 10:37:03 -06:00
|
|
|
nbread = if ncreq > nbreq { ncreq } else { nbreq };
|
2012-09-26 12:13:43 -05:00
|
|
|
if nbread > 0 {
|
2013-06-27 04:48:50 -05:00
|
|
|
bytes = bytes.slice(offset, bytes.len()).to_owned();
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
chars
|
2012-01-08 10:37:03 -06:00
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_char(&self) -> char {
|
2012-09-26 12:13:43 -05:00
|
|
|
let c = self.read_chars(1);
|
2013-05-14 04:52:12 -05:00
|
|
|
if c.len() == 0 {
|
2013-09-03 18:24:12 -05:00
|
|
|
return unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(c.len(), 1);
|
2012-08-01 19:30:05 -05:00
|
|
|
return c[0];
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_c_str(&self) -> ~str {
|
2013-04-18 08:36:38 -05:00
|
|
|
self.read_until(0u8, false)
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_whole_stream(&self) -> ~[u8] {
|
2012-10-18 11:10:37 -05:00
|
|
|
let mut bytes: ~[u8] = ~[];
|
|
|
|
while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
|
2013-02-15 02:51:28 -06:00
|
|
|
bytes
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
2012-05-01 10:14:56 -05:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_byte(&self, it: &fn(int) -> bool) -> bool {
|
2013-07-28 07:53:00 -05:00
|
|
|
loop {
|
|
|
|
match self.read_byte() {
|
|
|
|
-1 => break,
|
|
|
|
ch => if !it(ch) { return false; }
|
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2012-05-01 10:14:56 -05:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_char(&self, it: &fn(char) -> bool) -> bool {
|
2013-09-03 18:24:12 -05:00
|
|
|
// FIXME: #8971: unsound
|
|
|
|
let eof: char = unsafe { transmute(-1u32) };
|
2013-07-28 07:53:00 -05:00
|
|
|
loop {
|
|
|
|
match self.read_char() {
|
2013-09-03 18:24:12 -05:00
|
|
|
c if c == eof => break,
|
2013-07-28 07:53:00 -05:00
|
|
|
ch => if !it(ch) { return false; }
|
|
|
|
}
|
2013-05-02 17:33:18 -05:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2012-05-01 10:14:56 -05:00
|
|
|
|
2013-05-02 17:33:18 -05:00
|
|
|
fn each_line(&self, it: &fn(s: &str) -> bool) -> bool {
|
|
|
|
while !self.eof() {
|
|
|
|
// include the \n, so that we can distinguish an entirely empty
|
|
|
|
// line read after "...\n", and the trailing empty line in
|
|
|
|
// "...\n\n".
|
|
|
|
let mut line = self.read_until('\n' as u8, true);
|
|
|
|
|
|
|
|
// blank line at the end of the reader is ignored
|
|
|
|
if self.eof() && line.is_empty() { break; }
|
|
|
|
|
|
|
|
// trim the \n, so that each_line is consistent with read_line
|
2013-06-09 09:44:58 -05:00
|
|
|
let n = line.len();
|
2013-05-02 17:33:18 -05:00
|
|
|
if line[n-1] == '\n' as u8 {
|
|
|
|
unsafe { str::raw::set_len(&mut line, n-1); }
|
|
|
|
}
|
|
|
|
|
|
|
|
if !it(line) { return false; }
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2013-03-14 01:41:28 -05:00
|
|
|
|
|
|
|
fn read_lines(&self) -> ~[~str] {
|
2013-09-09 22:50:11 -05:00
|
|
|
do vec::build(None) |push| {
|
2013-07-31 14:07:44 -05:00
|
|
|
do self.each_line |line| {
|
2013-07-23 08:49:17 -05:00
|
|
|
push(line.to_owned());
|
2013-07-31 14:07:44 -05:00
|
|
|
true
|
|
|
|
};
|
2012-05-01 10:14:56 -05:00
|
|
|
}
|
|
|
|
}
|
2012-11-04 04:14:49 -06:00
|
|
|
|
|
|
|
// FIXME int reading methods need to deal with eof - issue #2004
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_uint_n(&self, nbytes: uint) -> u64 {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(nbytes > 0 && nbytes <= 8);
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-06-06 20:54:14 -05:00
|
|
|
let mut val = 0u64;
|
|
|
|
let mut pos = 0;
|
|
|
|
let mut i = nbytes;
|
2012-11-04 04:14:49 -06:00
|
|
|
while i > 0 {
|
|
|
|
val += (self.read_u8() as u64) << pos;
|
|
|
|
pos += 8;
|
|
|
|
i -= 1;
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_int_n(&self, nbytes: uint) -> i64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
extend_sign(self.read_le_uint_n(nbytes), nbytes)
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_uint_n(&self, nbytes: uint) -> u64 {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(nbytes > 0 && nbytes <= 8);
|
2012-11-04 04:14:49 -06:00
|
|
|
|
2013-06-06 20:54:14 -05:00
|
|
|
let mut val = 0u64;
|
|
|
|
let mut i = nbytes;
|
2012-11-04 04:14:49 -06:00
|
|
|
while i > 0 {
|
|
|
|
i -= 1;
|
|
|
|
val += (self.read_u8() as u64) << i * 8;
|
|
|
|
}
|
|
|
|
val
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_int_n(&self, nbytes: uint) -> i64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
extend_sign(self.read_be_uint_n(nbytes), nbytes)
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_uint(&self) -> uint {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_uint_n(uint::bytes) as uint
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_int(&self) -> int {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_int_n(int::bytes) as int
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_uint(&self) -> uint {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_uint_n(uint::bytes) as uint
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_int(&self) -> int {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_int_n(int::bytes) as int
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u64(&self) -> u64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_uint_n(8) as u64
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u32(&self) -> u32 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_uint_n(4) as u32
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_u16(&self) -> u16 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_uint_n(2) as u16
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i64(&self) -> i64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_int_n(8) as i64
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i32(&self) -> i32 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_int_n(4) as i32
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_be_i16(&self) -> i16 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_be_int_n(2) as i16
|
|
|
|
}
|
|
|
|
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_be_f64(&self) -> f64 {
|
|
|
|
unsafe {
|
|
|
|
cast::transmute::<u64, f64>(self.read_be_u64())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_be_f32(&self) -> f32 {
|
|
|
|
unsafe {
|
|
|
|
cast::transmute::<u32, f32>(self.read_be_u32())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u64(&self) -> u64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_uint_n(8) as u64
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u32(&self) -> u32 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_uint_n(4) as u32
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_u16(&self) -> u16 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_uint_n(2) as u16
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i64(&self) -> i64 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_int_n(8) as i64
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i32(&self) -> i32 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_int_n(4) as i32
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_le_i16(&self) -> i16 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_le_int_n(2) as i16
|
|
|
|
}
|
|
|
|
|
2013-03-05 18:07:04 -06:00
|
|
|
fn read_le_f64(&self) -> f64 {
|
|
|
|
unsafe {
|
|
|
|
cast::transmute::<u64, f64>(self.read_le_u64())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_le_f32(&self) -> f32 {
|
|
|
|
unsafe {
|
|
|
|
cast::transmute::<u32, f32>(self.read_le_u32())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_u8(&self) -> u8 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_byte() as u8
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_i8(&self) -> i8 {
|
2012-11-04 04:14:49 -06:00
|
|
|
self.read_byte() as i8
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn extend_sign(val: u64, nbytes: uint) -> i64 {
|
|
|
|
let shift = (8 - nbytes) * 8;
|
|
|
|
(val << shift) as i64 >> shift
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reader implementations
|
|
|
|
|
2012-08-14 15:38:35 -05:00
|
|
|
fn convert_whence(whence: SeekStyle) -> i32 {
|
2012-08-06 14:34:08 -05:00
|
|
|
return match whence {
|
2012-08-14 15:38:35 -05:00
|
|
|
SeekSet => 0i32,
|
|
|
|
SeekCur => 1i32,
|
|
|
|
SeekEnd => 2i32
|
2012-01-11 08:15:54 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Reader for *libc::FILE {
|
2013-02-11 22:18:34 -06:00
|
|
|
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-07-03 01:34:17 -05:00
|
|
|
do bytes.as_mut_buf |buf_p, buf_len| {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(buf_len >= len);
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
|
2013-05-07 16:01:04 -05:00
|
|
|
len as size_t, *self) as uint;
|
|
|
|
if count < len {
|
|
|
|
match libc::ferror(*self) {
|
|
|
|
0 => (),
|
|
|
|
_ => {
|
2013-10-21 15:08:31 -05:00
|
|
|
error!("error reading buffer: {}", os::last_os_error());
|
|
|
|
fail!();
|
2013-05-07 16:01:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2013-05-07 16:01:04 -05:00
|
|
|
count
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn read_byte(&self) -> int {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
libc::fgetc(*self) as int
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn eof(&self) -> bool {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return libc::feof(*self) != 0 as c_int;
|
2012-03-12 22:04:27 -05:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, offset: int, whence: SeekStyle) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(libc::fseek(*self,
|
2013-08-12 01:06:06 -05:00
|
|
|
offset as libc::c_long,
|
2013-03-06 15:58:02 -06:00
|
|
|
convert_whence(whence)) == 0 as c_int);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn tell(&self) -> uint {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return libc::ftell(*self) as uint;
|
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-01-24 14:54:24 -06:00
|
|
|
struct Wrapper<T, C> {
|
|
|
|
base: T,
|
|
|
|
cleanup: C,
|
|
|
|
}
|
|
|
|
|
2012-01-11 08:15:54 -06:00
|
|
|
// A forwarding impl of reader that also holds on to a resource for the
|
|
|
|
// duration of its lifetime.
|
2012-03-15 23:04:17 -05:00
|
|
|
// FIXME there really should be a better way to do this // #2004
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<R:Reader,C> Reader for Wrapper<R, C> {
|
2013-02-11 22:18:34 -06:00
|
|
|
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
2012-10-18 11:10:37 -05:00
|
|
|
self.base.read(bytes, len)
|
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_byte(&self) -> int { self.base.read_byte() }
|
|
|
|
fn eof(&self) -> bool { self.base.eof() }
|
|
|
|
fn seek(&self, off: int, whence: SeekStyle) {
|
|
|
|
self.base.seek(off, whence)
|
|
|
|
}
|
|
|
|
fn tell(&self) -> uint { self.base.tell() }
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
pub struct FILERes {
|
2013-10-19 19:33:09 -05:00
|
|
|
priv f: *libc::FILE,
|
2013-02-27 18:13:53 -06:00
|
|
|
}
|
|
|
|
|
2013-06-04 05:47:45 -05:00
|
|
|
impl FILERes {
|
|
|
|
pub fn new(f: *libc::FILE) -> FILERes {
|
|
|
|
FILERes { f: f }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-27 18:13:53 -06:00
|
|
|
impl Drop for FILERes {
|
2013-09-16 20:18:07 -05:00
|
|
|
fn drop(&mut self) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
libc::fclose(self.f);
|
|
|
|
}
|
|
|
|
}
|
2012-06-21 23:30:16 -05:00
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
|
2013-02-04 15:33:17 -06:00
|
|
|
pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
|
2012-01-11 08:15:54 -06:00
|
|
|
if cleanup {
|
2013-06-04 05:47:45 -05:00
|
|
|
@Wrapper { base: f, cleanup: FILERes::new(f) } as @Reader
|
2012-01-11 08:15:54 -06:00
|
|
|
} else {
|
2013-02-04 15:33:17 -06:00
|
|
|
@f as @Reader
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-31 12:27:51 -05:00
|
|
|
// FIXME (#2004): this should either be an trait-less impl, a set of
|
2012-06-21 18:44:10 -05:00
|
|
|
// top-level functions that take a reader, or a set of default methods on
|
|
|
|
// reader (which can then be called reader)
|
2012-01-11 08:15:54 -06:00
|
|
|
|
2013-05-19 14:33:01 -05:00
|
|
|
/**
|
|
|
|
* Gives a `Reader` that allows you to read values from standard input.
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
|
|
|
*
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```rust
|
2013-08-16 00:54:14 -05:00
|
|
|
* let stdin = std::io::stdin();
|
2013-05-19 14:33:01 -05:00
|
|
|
* let line = stdin.read_line();
|
2013-08-16 00:54:14 -05:00
|
|
|
* std::io::print(line);
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```
|
2013-05-19 14:33:01 -05:00
|
|
|
*/
|
2013-02-04 15:33:17 -06:00
|
|
|
pub fn stdin() -> @Reader {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-02-26 20:42:00 -06:00
|
|
|
@rustrt::rust_get_stdin() as @Reader
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
|
2013-02-04 15:33:17 -06:00
|
|
|
pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-08-14 21:21:59 -05:00
|
|
|
let f = do path.with_c_str |pathbuf| {
|
|
|
|
do "rb".with_c_str |modebuf| {
|
2013-06-30 10:25:16 -05:00
|
|
|
unsafe { libc::fopen(pathbuf, modebuf as *libc::c_char) }
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2013-06-30 10:25:16 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
if f as uint == 0u {
|
2013-10-06 20:51:49 -05:00
|
|
|
do path.display().with_str |p| {
|
2013-09-26 19:21:59 -05:00
|
|
|
Err(~"error opening " + p)
|
|
|
|
}
|
2013-06-30 10:25:16 -05:00
|
|
|
} else {
|
2013-07-24 22:23:38 -05:00
|
|
|
Ok(FILE_reader(f, true))
|
2011-10-28 23:19:59 -05:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-10-18 11:06:53 -05:00
|
|
|
// Byte readers
|
2013-06-20 19:18:16 -05:00
|
|
|
pub struct BytesReader {
|
|
|
|
// FIXME(#5723) see other FIXME below
|
|
|
|
// FIXME(#7268) this should also be parameterized over <'self>
|
|
|
|
bytes: &'static [u8],
|
2013-05-03 19:37:08 -05:00
|
|
|
pos: @mut uint
|
2012-10-18 11:06:53 -05:00
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-06-20 19:18:16 -05:00
|
|
|
impl Reader for BytesReader {
|
2013-02-11 22:18:34 -06:00
|
|
|
fn read(&self, bytes: &mut [u8], len: uint) -> uint {
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
let count = num::min(len, self.bytes.len() - *self.pos);
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2013-06-27 04:48:50 -05:00
|
|
|
let view = self.bytes.slice(*self.pos, self.bytes.len());
|
2013-01-10 01:11:04 -06:00
|
|
|
vec::bytes::copy_memory(bytes, view, count);
|
2012-07-20 23:49:20 -05:00
|
|
|
|
2013-05-03 19:37:08 -05:00
|
|
|
*self.pos += count;
|
2012-07-20 23:49:20 -05:00
|
|
|
|
|
|
|
count
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-05-03 19:37:08 -05:00
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn read_byte(&self) -> int {
|
2013-05-03 19:37:08 -05:00
|
|
|
if *self.pos == self.bytes.len() {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
let b = self.bytes[*self.pos];
|
|
|
|
*self.pos += 1u;
|
|
|
|
b as int
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-05-03 19:37:08 -05:00
|
|
|
|
|
|
|
fn eof(&self) -> bool {
|
|
|
|
*self.pos == self.bytes.len()
|
|
|
|
}
|
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, offset: int, whence: SeekStyle) {
|
2013-05-03 19:37:08 -05:00
|
|
|
let pos = *self.pos;
|
|
|
|
*self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tell(&self) -> uint {
|
|
|
|
*self.pos
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-03 19:37:08 -05:00
|
|
|
pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
|
2013-06-20 19:18:16 -05:00
|
|
|
// XXX XXX XXX this is glaringly unsound
|
|
|
|
// FIXME(#5723) Use a &Reader for the callback's argument. Should be:
|
|
|
|
// fn with_bytes_reader<'r, T>(bytes: &'r [u8], f: &fn(&'r Reader) -> T) -> T
|
|
|
|
let bytes: &'static [u8] = unsafe { cast::transmute(bytes) };
|
2013-05-03 19:37:08 -05:00
|
|
|
f(@BytesReader {
|
|
|
|
bytes: bytes,
|
|
|
|
pos: @mut 0
|
|
|
|
} as @Reader)
|
2012-02-29 12:48:57 -06:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
|
2013-06-20 19:18:16 -05:00
|
|
|
// FIXME(#5723): As above.
|
2013-06-10 22:10:37 -05:00
|
|
|
with_bytes_reader(s.as_bytes(), f)
|
2012-02-29 12:48:57 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
|
|
|
|
// Writing
|
2012-10-01 16:02:10 -05:00
|
|
|
pub enum FileFlag { Append, Create, Truncate, NoFlag, }
|
2011-07-10 14:47:51 -05:00
|
|
|
|
2012-07-26 16:47:51 -05:00
|
|
|
// What type of writer are we?
|
2013-03-20 10:35:02 -05:00
|
|
|
#[deriving(Eq)]
|
2012-10-01 16:02:10 -05:00
|
|
|
pub enum WriterType { Screen, File }
|
2012-07-26 16:47:51 -05:00
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004): Seekable really should be orthogonal.
|
|
|
|
// FIXME (#2004): eventually u64
|
2012-11-04 12:11:37 -06:00
|
|
|
/// The raw underlying writer trait. All writers must implement this.
|
2012-10-01 16:02:10 -05:00
|
|
|
pub trait Writer {
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write all of the given bytes.
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, v: &[u8]);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Move the current position within the stream. The second parameter
|
|
|
|
/// determines the position that the first parameter is relative to.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, int, SeekStyle);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Return the current position within the stream.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn tell(&self) -> uint;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Flush the output buffer for this stream (if there is one).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn flush(&self) -> int;
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Determine if this Writer is writing to a file or not.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn get_type(&self) -> WriterType;
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
|
|
|
|
2013-03-05 16:49:50 -06:00
|
|
|
impl Writer for @Writer {
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, v: &[u8]) { self.write(v) }
|
2013-03-05 16:49:50 -06:00
|
|
|
fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
|
|
|
|
fn tell(&self) -> uint { self.tell() }
|
|
|
|
fn flush(&self) -> int { self.flush() }
|
|
|
|
fn get_type(&self) -> WriterType { self.get_type() }
|
|
|
|
}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<W:Writer,C> Writer for Wrapper<W, C> {
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, bs: &[u8]) { self.base.write(bs); }
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
|
|
|
|
fn tell(&self) -> uint { self.base.tell() }
|
|
|
|
fn flush(&self) -> int { self.base.flush() }
|
|
|
|
fn get_type(&self) -> WriterType { File }
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Writer for *libc::FILE {
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, v: &[u8]) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-07-03 01:34:17 -05:00
|
|
|
do v.as_imm_buf |vbuf, len| {
|
2013-01-10 23:23:07 -06:00
|
|
|
let nout = libc::fwrite(vbuf as *c_void,
|
|
|
|
1,
|
|
|
|
len as size_t,
|
|
|
|
*self);
|
|
|
|
if nout != len as size_t {
|
2013-10-21 15:08:31 -05:00
|
|
|
error!("error writing buffer: {}", os::last_os_error());
|
|
|
|
fail!();
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-03-12 22:04:27 -05:00
|
|
|
}
|
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, offset: int, whence: SeekStyle) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(libc::fseek(*self,
|
2013-08-12 01:06:06 -05:00
|
|
|
offset as libc::c_long,
|
2013-03-06 15:58:02 -06:00
|
|
|
convert_whence(whence)) == 0 as c_int);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn tell(&self) -> uint {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
libc::ftell(*self) as uint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn flush(&self) -> int {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
libc::fflush(*self) as int
|
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn get_type(&self) -> WriterType {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let fd = libc::fileno(*self);
|
|
|
|
if libc::isatty(fd) == 0 { File }
|
|
|
|
else { Screen }
|
|
|
|
}
|
2012-07-26 16:47:51 -05:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Writer for fd_t {
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, v: &[u8]) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-08-12 01:06:06 -05:00
|
|
|
#[cfg(windows)]
|
|
|
|
type IoSize = libc::c_uint;
|
|
|
|
#[cfg(windows)]
|
|
|
|
type IoRet = c_int;
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
type IoSize = size_t;
|
|
|
|
#[cfg(unix)]
|
|
|
|
type IoRet = libc::ssize_t;
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let mut count = 0u;
|
2013-07-03 01:34:17 -05:00
|
|
|
do v.as_imm_buf |vbuf, len| {
|
2013-01-10 23:23:07 -06:00
|
|
|
while count < len {
|
2013-07-29 23:33:52 -05:00
|
|
|
let vb = ptr::offset(vbuf, count as int) as *c_void;
|
2013-08-12 01:06:06 -05:00
|
|
|
let nout = libc::write(*self, vb, len as IoSize);
|
|
|
|
if nout < 0 as IoRet {
|
2013-10-21 15:08:31 -05:00
|
|
|
error!("error writing buffer: {}", os::last_os_error());
|
|
|
|
fail!();
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
count += nout as uint;
|
2012-03-12 22:04:27 -05:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, _offset: int, _whence: SeekStyle) {
|
2013-10-21 15:08:31 -05:00
|
|
|
error!("need 64-bit foreign calls for seek, sorry");
|
|
|
|
fail!();
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn tell(&self) -> uint {
|
2013-10-21 15:08:31 -05:00
|
|
|
error!("need 64-bit foreign calls for tell, sorry");
|
|
|
|
fail!();
|
2011-07-27 10:05:34 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn flush(&self) -> int { 0 }
|
|
|
|
fn get_type(&self) -> WriterType {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
if libc::isatty(*self) == 0 { File } else { Screen }
|
|
|
|
}
|
2012-07-26 16:47:51 -05:00
|
|
|
}
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
|
2013-01-08 21:37:25 -06:00
|
|
|
pub struct FdRes {
|
2013-10-19 19:33:09 -05:00
|
|
|
priv fd: fd_t,
|
2013-02-27 18:13:53 -06:00
|
|
|
}
|
|
|
|
|
2013-06-04 05:47:45 -05:00
|
|
|
impl FdRes {
|
|
|
|
pub fn new(fd: fd_t) -> FdRes {
|
|
|
|
FdRes { fd: fd }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-27 18:13:53 -06:00
|
|
|
impl Drop for FdRes {
|
2013-09-16 20:18:07 -05:00
|
|
|
fn drop(&mut self) {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
libc::close(self.fd);
|
|
|
|
}
|
|
|
|
}
|
2012-06-21 23:30:16 -05:00
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
|
2013-02-26 20:42:00 -06:00
|
|
|
pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
|
2012-01-11 08:15:54 -06:00
|
|
|
if cleanup {
|
2013-06-04 05:47:45 -05:00
|
|
|
@Wrapper { base: fd, cleanup: FdRes::new(fd) } as @Writer
|
2012-01-11 08:15:54 -06:00
|
|
|
} else {
|
2013-02-26 20:42:00 -06:00
|
|
|
@fd as @Writer
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2012-03-12 22:04:27 -05:00
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
|
2013-03-12 15:00:50 -05:00
|
|
|
-> Result<@Writer, ~str> {
|
2013-08-14 20:41:40 -05:00
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
2012-06-07 23:38:25 -05:00
|
|
|
#[cfg(windows)]
|
2013-02-26 23:10:03 -06:00
|
|
|
fn wb() -> c_int {
|
|
|
|
(O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
|
|
|
|
}
|
2012-03-12 22:04:27 -05:00
|
|
|
|
2012-06-07 23:38:25 -05:00
|
|
|
#[cfg(unix)]
|
2012-03-12 22:04:27 -05:00
|
|
|
fn wb() -> c_int { O_WRONLY as c_int }
|
|
|
|
|
|
|
|
let mut fflags: c_int = wb();
|
2013-08-03 11:45:23 -05:00
|
|
|
for f in flags.iter() {
|
2012-09-18 23:41:37 -05:00
|
|
|
match *f {
|
2012-08-14 15:38:35 -05:00
|
|
|
Append => fflags |= O_APPEND as c_int,
|
|
|
|
Create => fflags |= O_CREAT as c_int,
|
|
|
|
Truncate => fflags |= O_TRUNC as c_int,
|
|
|
|
NoFlag => ()
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
}
|
2013-01-10 23:23:07 -06:00
|
|
|
let fd = unsafe {
|
2013-08-14 21:21:59 -05:00
|
|
|
do path.with_c_str |pathbuf| {
|
2013-08-03 19:13:14 -05:00
|
|
|
libc::open(pathbuf, fflags, (S_IRUSR | S_IWUSR) as c_int)
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-03-12 22:04:27 -05:00
|
|
|
};
|
|
|
|
if fd < (0 as c_int) {
|
2013-09-26 19:21:59 -05:00
|
|
|
Err(format!("error opening {}: {}", path.display(), os::last_os_error()))
|
2011-10-28 23:19:59 -05:00
|
|
|
} else {
|
2013-07-24 22:23:38 -05:00
|
|
|
Ok(fd_writer(fd, true))
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn u64_to_le_bytes<T>(n: u64, size: uint,
|
2013-03-07 16:38:38 -06:00
|
|
|
f: &fn(v: &[u8]) -> T) -> T {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(size <= 8u);
|
2012-08-06 14:34:08 -05:00
|
|
|
match size {
|
2012-08-03 21:59:04 -05:00
|
|
|
1u => f(&[n as u8]),
|
|
|
|
2u => f(&[n as u8,
|
|
|
|
(n >> 8) as u8]),
|
|
|
|
4u => f(&[n as u8,
|
2012-04-25 19:18:06 -05:00
|
|
|
(n >> 8) as u8,
|
|
|
|
(n >> 16) as u8,
|
2012-08-03 21:59:04 -05:00
|
|
|
(n >> 24) as u8]),
|
|
|
|
8u => f(&[n as u8,
|
2012-04-25 19:18:06 -05:00
|
|
|
(n >> 8) as u8,
|
|
|
|
(n >> 16) as u8,
|
|
|
|
(n >> 24) as u8,
|
|
|
|
(n >> 32) as u8,
|
|
|
|
(n >> 40) as u8,
|
|
|
|
(n >> 48) as u8,
|
2012-08-03 21:59:04 -05:00
|
|
|
(n >> 56) as u8]),
|
|
|
|
_ => {
|
2012-04-25 19:18:06 -05:00
|
|
|
|
2013-06-04 23:43:41 -05:00
|
|
|
let mut bytes: ~[u8] = ~[];
|
|
|
|
let mut i = size;
|
|
|
|
let mut n = n;
|
2012-04-25 19:18:06 -05:00
|
|
|
while i > 0u {
|
2012-09-26 19:33:34 -05:00
|
|
|
bytes.push((n & 255_u64) as u8);
|
2012-04-25 19:18:06 -05:00
|
|
|
n >>= 8_u64;
|
|
|
|
i -= 1u;
|
|
|
|
}
|
|
|
|
f(bytes)
|
|
|
|
}
|
2012-02-14 17:21:53 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn u64_to_be_bytes<T>(n: u64, size: uint,
|
2013-03-07 16:38:38 -06:00
|
|
|
f: &fn(v: &[u8]) -> T) -> T {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(size <= 8u);
|
2012-08-06 14:34:08 -05:00
|
|
|
match size {
|
2012-08-03 21:59:04 -05:00
|
|
|
1u => f(&[n as u8]),
|
|
|
|
2u => f(&[(n >> 8) as u8,
|
|
|
|
n as u8]),
|
|
|
|
4u => f(&[(n >> 24) as u8,
|
2012-04-25 19:18:06 -05:00
|
|
|
(n >> 16) as u8,
|
|
|
|
(n >> 8) as u8,
|
2012-08-03 21:59:04 -05:00
|
|
|
n as u8]),
|
|
|
|
8u => f(&[(n >> 56) as u8,
|
2012-04-25 19:18:06 -05:00
|
|
|
(n >> 48) as u8,
|
|
|
|
(n >> 40) as u8,
|
|
|
|
(n >> 32) as u8,
|
|
|
|
(n >> 24) as u8,
|
|
|
|
(n >> 16) as u8,
|
|
|
|
(n >> 8) as u8,
|
2012-08-03 21:59:04 -05:00
|
|
|
n as u8]),
|
|
|
|
_ => {
|
2012-06-29 18:26:56 -05:00
|
|
|
let mut bytes: ~[u8] = ~[];
|
2012-04-25 19:18:06 -05:00
|
|
|
let mut i = size;
|
|
|
|
while i > 0u {
|
|
|
|
let shift = ((i - 1u) * 8u) as u64;
|
2012-09-26 19:33:34 -05:00
|
|
|
bytes.push((n >> shift) as u8);
|
2012-04-25 19:18:06 -05:00
|
|
|
i -= 1u;
|
|
|
|
}
|
|
|
|
f(bytes)
|
|
|
|
}
|
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-03-15 14:24:24 -05:00
|
|
|
pub fn u64_from_be_bytes(data: &[u8],
|
2013-03-22 19:58:50 -05:00
|
|
|
start: uint,
|
|
|
|
size: uint)
|
|
|
|
-> u64 {
|
2012-03-12 22:04:27 -05:00
|
|
|
let mut sz = size;
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!((sz <= 8u));
|
2012-03-12 22:04:27 -05:00
|
|
|
let mut val = 0_u64;
|
|
|
|
let mut pos = start;
|
2012-02-14 17:21:53 -06:00
|
|
|
while sz > 0u {
|
|
|
|
sz -= 1u;
|
|
|
|
val += (data[pos] as u64) << ((sz * 8u) as u64);
|
|
|
|
pos += 1u;
|
|
|
|
}
|
2012-08-01 19:30:05 -05:00
|
|
|
return val;
|
2012-02-14 17:21:53 -06:00
|
|
|
}
|
|
|
|
|
2012-08-02 19:17:07 -05:00
|
|
|
// FIXME: #3048 combine trait+impl (or just move these to
|
|
|
|
// default methods on writer)
|
2012-11-04 12:11:37 -06:00
|
|
|
/// Generic utility functions defined on writers.
|
2012-10-01 16:02:10 -05:00
|
|
|
pub trait WriterUtil {
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a single utf-8 encoded char.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_char(&self, ch: char);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write every char in the given str, encoded as utf-8.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_str(&self, s: &str);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write the given str, as utf-8, followed by '\n'.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_line(&self, s: &str);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write the result of passing n through `int::to_str_bytes`.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_int(&self, n: int);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write the result of passing n through `uint::to_str_bytes`.
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_uint(&self, n: uint);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian uint (number of bytes depends on system).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_uint(&self, n: uint);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian int (number of bytes depends on system).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_int(&self, n: int);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian uint (number of bytes depends on system).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_uint(&self, n: uint);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian int (number of bytes depends on system).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_int(&self, n: int);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian u64 (8 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u64(&self, n: u64);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian u32 (4 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u32(&self, n: u32);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian u16 (2 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u16(&self, n: u16);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian i64 (8 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i64(&self, n: i64);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian i32 (4 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i32(&self, n: i32);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a big-endian i16 (2 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i16(&self, n: i16);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-03-05 18:07:04 -06:00
|
|
|
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
|
|
|
|
fn write_be_f64(&self, f: f64);
|
|
|
|
|
|
|
|
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
|
|
|
|
fn write_be_f32(&self, f: f32);
|
|
|
|
|
2012-11-04 12:11:37 -06:00
|
|
|
/// Write a little-endian u64 (8 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u64(&self, n: u64);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian u32 (4 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u32(&self, n: u32);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian u16 (2 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u16(&self, n: u16);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian i64 (8 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i64(&self, n: i64);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian i32 (4 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i32(&self, n: i32);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a little-endian i16 (2 bytes).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i16(&self, n: i16);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
2013-03-05 18:07:04 -06:00
|
|
|
/// Write a little-endian IEEE754 double-precision floating-point
|
|
|
|
/// (8 bytes).
|
|
|
|
fn write_le_f64(&self, f: f64);
|
|
|
|
|
2013-08-17 17:28:04 -05:00
|
|
|
/// Write a little-endian IEEE754 single-precision floating-point
|
2013-03-05 18:07:04 -06:00
|
|
|
/// (4 bytes).
|
|
|
|
fn write_le_f32(&self, f: f32);
|
|
|
|
|
2012-11-04 12:11:37 -06:00
|
|
|
/// Write a u8 (1 byte).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_u8(&self, n: u8);
|
2012-11-04 12:11:37 -06:00
|
|
|
|
|
|
|
/// Write a i8 (1 byte).
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_i8(&self, n: i8);
|
2012-08-02 19:17:07 -05:00
|
|
|
}
|
|
|
|
|
2013-02-20 19:07:17 -06:00
|
|
|
impl<T:Writer> WriterUtil for T {
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_char(&self, ch: char) {
|
2013-03-20 15:24:09 -05:00
|
|
|
if (ch as uint) < 128u {
|
2012-06-29 18:26:56 -05:00
|
|
|
self.write(&[ch as u8]);
|
2012-01-11 08:15:54 -06:00
|
|
|
} else {
|
2012-04-25 19:18:06 -05:00
|
|
|
self.write_str(str::from_char(ch));
|
2012-01-11 08:15:54 -06:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-06-10 22:10:37 -05:00
|
|
|
fn write_str(&self, s: &str) { self.write(s.as_bytes()) }
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_line(&self, s: &str) {
|
2012-04-25 19:18:06 -05:00
|
|
|
self.write_str(s);
|
2012-07-14 00:57:48 -05:00
|
|
|
self.write_str(&"\n");
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_int(&self, n: int) {
|
2012-10-18 11:10:37 -05:00
|
|
|
int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
2012-06-04 20:05:34 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_uint(&self, n: uint) {
|
2013-01-24 14:47:57 -06:00
|
|
|
uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
|
2012-06-04 20:05:34 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_uint(&self, n: uint) {
|
2012-08-02 19:17:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_int(&self, n: int) {
|
2012-08-02 19:17:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_uint(&self, n: uint) {
|
2012-08-02 19:17:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_int(&self, n: int) {
|
2012-08-02 19:17:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u64(&self, n: u64) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n, 8u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u32(&self, n: u32) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_u16(&self, n: u16) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i64(&self, n: i64) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i32(&self, n: i32) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_be_i16(&self, n: i16) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2013-03-05 18:07:04 -06:00
|
|
|
fn write_be_f64(&self, f:f64) {
|
|
|
|
unsafe {
|
|
|
|
self.write_be_u64(cast::transmute(f))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn write_be_f32(&self, f:f32) {
|
|
|
|
unsafe {
|
|
|
|
self.write_be_u32(cast::transmute(f))
|
|
|
|
}
|
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u64(&self, n: u64) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n, 8u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u32(&self, n: u32) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_u16(&self, n: u16) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i64(&self, n: i64) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i32(&self, n: i32) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
|
2012-04-25 19:18:06 -05:00
|
|
|
}
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_le_i16(&self, n: i16) {
|
2012-06-30 18:19:07 -05:00
|
|
|
u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
|
2012-02-14 17:21:53 -06:00
|
|
|
}
|
2013-03-05 18:07:04 -06:00
|
|
|
fn write_le_f64(&self, f:f64) {
|
|
|
|
unsafe {
|
|
|
|
self.write_le_u64(cast::transmute(f))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn write_le_f32(&self, f:f32) {
|
|
|
|
unsafe {
|
|
|
|
self.write_le_u32(cast::transmute(f))
|
|
|
|
}
|
|
|
|
}
|
2012-02-14 17:21:53 -06:00
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn write_u8(&self, n: u8) { self.write([n]) }
|
|
|
|
fn write_i8(&self, n: i8) { self.write([n as u8]) }
|
2013-03-05 18:07:04 -06:00
|
|
|
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2013-03-12 15:00:50 -05:00
|
|
|
pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
|
2013-09-11 14:52:17 -05:00
|
|
|
mk_file_writer(path, flags).and_then(|w| Ok(w))
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004) it would be great if this could be a const
|
|
|
|
// FIXME (#2004) why are these different from the way stdin() is
|
|
|
|
// implemented?
|
2013-05-19 14:06:39 -05:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gives a `Writer` which allows you to write to the standard output.
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
|
|
|
*
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```rust
|
2013-08-16 00:54:14 -05:00
|
|
|
* let stdout = std::io::stdout();
|
2013-05-19 14:06:39 -05:00
|
|
|
* stdout.write_str("hello\n");
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```
|
2013-05-19 14:06:39 -05:00
|
|
|
*/
|
2013-03-05 16:49:50 -06:00
|
|
|
pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
|
2013-05-19 14:06:39 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gives a `Writer` which allows you to write to standard error.
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
|
|
|
*
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```rust
|
2013-08-16 00:54:14 -05:00
|
|
|
* let stderr = std::io::stderr();
|
2013-05-19 14:06:39 -05:00
|
|
|
* stderr.write_str("hello\n");
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```
|
2013-05-19 14:06:39 -05:00
|
|
|
*/
|
2013-03-05 16:49:50 -06:00
|
|
|
pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
|
2011-07-10 14:47:51 -05:00
|
|
|
|
2013-05-19 14:06:39 -05:00
|
|
|
/**
|
|
|
|
* Prints a string to standard output.
|
2013-05-19 17:31:19 -05:00
|
|
|
*
|
2013-05-19 14:06:39 -05:00
|
|
|
* This string will not have an implicit newline at the end. If you want
|
|
|
|
* an implicit newline, please see `println`.
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
|
|
|
*
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```rust
|
2013-05-19 14:42:00 -05:00
|
|
|
* // print is imported into the prelude, and so is always available.
|
|
|
|
* print("hello");
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```
|
2013-05-19 14:06:39 -05:00
|
|
|
*/
|
2013-05-03 19:37:08 -05:00
|
|
|
pub fn print(s: &str) {
|
|
|
|
stdout().write_str(s);
|
|
|
|
}
|
|
|
|
|
2013-05-19 14:06:39 -05:00
|
|
|
/**
|
|
|
|
* Prints a string to standard output, followed by a newline.
|
2013-05-19 17:31:19 -05:00
|
|
|
*
|
2013-05-19 14:06:39 -05:00
|
|
|
* If you do not want an implicit newline, please see `print`.
|
|
|
|
*
|
2013-05-27 08:49:54 -05:00
|
|
|
* # Example
|
|
|
|
*
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```rust
|
2013-05-19 14:42:00 -05:00
|
|
|
* // println is imported into the prelude, and so is always available.
|
|
|
|
* println("hello");
|
2013-09-23 19:20:36 -05:00
|
|
|
* ```
|
2013-05-19 14:06:39 -05:00
|
|
|
*/
|
2013-05-03 19:37:08 -05:00
|
|
|
pub fn println(s: &str) {
|
|
|
|
stdout().write_line(s);
|
|
|
|
}
|
2011-12-28 02:30:04 -06:00
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub struct BytesWriter {
|
2013-05-03 19:37:08 -05:00
|
|
|
bytes: @mut ~[u8],
|
|
|
|
pos: @mut uint,
|
2012-09-14 11:40:28 -05:00
|
|
|
}
|
2011-07-10 14:47:51 -05:00
|
|
|
|
2013-06-04 05:47:45 -05:00
|
|
|
impl BytesWriter {
|
|
|
|
pub fn new() -> BytesWriter {
|
|
|
|
BytesWriter {
|
|
|
|
bytes: @mut ~[],
|
|
|
|
pos: @mut 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl Writer for BytesWriter {
|
2013-03-15 14:24:24 -05:00
|
|
|
fn write(&self, v: &[u8]) {
|
2013-03-07 17:36:35 -06:00
|
|
|
let v_len = v.len();
|
2012-08-26 23:21:59 -05:00
|
|
|
|
2013-05-07 13:38:08 -05:00
|
|
|
let bytes = &mut *self.bytes;
|
Replaces the free-standing functions in f32, &c.
The free-standing functions in f32, f64, i8, i16, i32, i64, u8, u16,
u32, u64, float, int, and uint are replaced with generic functions in
num instead.
If you were previously using any of those functions, just replace them
with the corresponding function with the same name in num.
Note: If you were using a function that corresponds to an operator, use
the operator instead.
2013-07-08 11:05:17 -05:00
|
|
|
let count = num::max(bytes.len(), *self.pos + v_len);
|
2013-06-27 09:40:47 -05:00
|
|
|
bytes.reserve(count);
|
2012-05-11 12:44:57 -05:00
|
|
|
|
2013-03-07 17:36:35 -06:00
|
|
|
unsafe {
|
2013-06-20 00:15:50 -05:00
|
|
|
vec::raw::set_len(bytes, count);
|
2013-05-07 13:38:08 -05:00
|
|
|
|
2013-06-27 04:48:50 -05:00
|
|
|
let view = bytes.mut_slice(*self.pos, count);
|
2013-03-07 17:36:35 -06:00
|
|
|
vec::bytes::copy_memory(view, v, v_len);
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-03-07 17:36:35 -06:00
|
|
|
|
2013-05-03 19:37:08 -05:00
|
|
|
*self.pos += v_len;
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2013-05-03 19:37:08 -05:00
|
|
|
|
2012-12-24 12:52:53 -06:00
|
|
|
fn seek(&self, offset: int, whence: SeekStyle) {
|
2013-05-03 19:37:08 -05:00
|
|
|
let pos = *self.pos;
|
2013-06-15 01:20:06 -05:00
|
|
|
let len = self.bytes.len();
|
2013-05-03 19:37:08 -05:00
|
|
|
*self.pos = seek_in_buf(offset, pos, len, whence);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn tell(&self) -> uint {
|
|
|
|
*self.pos
|
|
|
|
}
|
|
|
|
|
|
|
|
fn flush(&self) -> int {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_type(&self) -> WriterType {
|
|
|
|
File
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2012-09-20 13:17:15 -05:00
|
|
|
}
|
|
|
|
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
|
2013-06-04 05:47:45 -05:00
|
|
|
let wr = @BytesWriter::new();
|
2013-03-12 15:00:50 -05:00
|
|
|
f(wr as @Writer);
|
2013-05-03 19:37:08 -05:00
|
|
|
let @BytesWriter { bytes, _ } = wr;
|
2013-07-02 14:47:32 -05:00
|
|
|
(*bytes).clone()
|
2012-02-21 11:23:01 -06:00
|
|
|
}
|
2012-02-21 11:22:50 -06:00
|
|
|
|
2013-08-04 15:22:56 -05:00
|
|
|
pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
|
2013-09-05 07:17:24 -05:00
|
|
|
str::from_utf8(with_bytes_writer(f))
|
2013-08-04 15:22:56 -05:00
|
|
|
}
|
|
|
|
|
2011-07-10 14:47:51 -05:00
|
|
|
// Utility functions
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
|
2011-07-27 07:19:39 -05:00
|
|
|
uint {
|
2012-03-12 22:04:27 -05:00
|
|
|
let mut bpos = pos as int;
|
2011-07-27 07:19:39 -05:00
|
|
|
let blen = len as int;
|
2012-08-06 14:34:08 -05:00
|
|
|
match whence {
|
2012-08-14 15:38:35 -05:00
|
|
|
SeekSet => bpos = offset,
|
|
|
|
SeekCur => bpos += offset,
|
|
|
|
SeekEnd => bpos = blen + offset
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2011-08-19 17:16:48 -05:00
|
|
|
if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
|
2012-08-01 19:30:05 -05:00
|
|
|
return bpos as uint;
|
2011-07-10 14:47:51 -05:00
|
|
|
}
|
2011-08-01 17:53:14 -05:00
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
|
2013-09-11 14:52:17 -05:00
|
|
|
do read_whole_file(file).and_then |bytes| {
|
2012-07-25 16:58:48 -05:00
|
|
|
if str::is_utf8(bytes) {
|
2013-09-05 07:17:24 -05:00
|
|
|
Ok(str::from_utf8(bytes))
|
2013-05-23 11:09:11 -05:00
|
|
|
} else {
|
2013-10-06 20:51:49 -05:00
|
|
|
Err(file.display().to_str() + " is not UTF-8")
|
2013-05-23 11:09:11 -05:00
|
|
|
}
|
2013-07-22 19:27:53 -05:00
|
|
|
}
|
2011-08-01 17:53:14 -05:00
|
|
|
}
|
|
|
|
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004): implement this in a low-level way. Going through the
|
|
|
|
// abstractions is pointless.
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
|
2013-09-11 14:52:17 -05:00
|
|
|
do file_reader(file).and_then |rdr| {
|
2013-07-24 22:23:38 -05:00
|
|
|
Ok(rdr.read_whole_stream())
|
2013-07-22 19:27:53 -05:00
|
|
|
}
|
2011-08-01 17:53:14 -05:00
|
|
|
}
|
|
|
|
|
2011-11-16 16:14:18 -06:00
|
|
|
// fsync related
|
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub mod fsync {
|
2013-01-08 21:37:25 -06:00
|
|
|
use io::{FILERes, FdRes, fd_t};
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
2013-03-21 10:04:24 -05:00
|
|
|
use ops::Drop;
|
|
|
|
use option::{None, Option, Some};
|
2012-12-23 16:41:37 -06:00
|
|
|
use os;
|
2011-11-16 16:14:18 -06:00
|
|
|
|
2012-10-01 16:02:10 -05:00
|
|
|
pub enum Level {
|
2011-11-16 16:14:18 -06:00
|
|
|
// whatever fsync does on that platform
|
2012-08-14 15:38:35 -05:00
|
|
|
FSync,
|
2011-11-16 16:14:18 -06:00
|
|
|
|
|
|
|
// fdatasync on linux, similiar or more on other platforms
|
2012-08-14 15:38:35 -05:00
|
|
|
FDataSync,
|
2011-11-16 16:14:18 -06:00
|
|
|
|
|
|
|
// full fsync
|
|
|
|
//
|
|
|
|
// You must additionally sync the parent directory as well!
|
2012-08-14 15:38:35 -05:00
|
|
|
FullFSync,
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-06-21 23:30:16 -05:00
|
|
|
// Artifacts that need to fsync on destruction
|
2013-01-28 12:46:43 -06:00
|
|
|
pub struct Res<t> {
|
2013-10-19 19:33:09 -05:00
|
|
|
priv arg: Arg<t>,
|
2013-01-22 09:51:00 -06:00
|
|
|
}
|
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
impl <t> Res<t> {
|
2013-06-04 05:47:45 -05:00
|
|
|
pub fn new(arg: Arg<t>) -> Res<t> {
|
|
|
|
Res { arg: arg }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-20 20:18:57 -05:00
|
|
|
#[unsafe_destructor]
|
2013-07-02 14:47:32 -05:00
|
|
|
impl<T> Drop for Res<T> {
|
2013-09-16 20:18:07 -05:00
|
|
|
fn drop(&mut self) {
|
2013-03-20 20:18:57 -05:00
|
|
|
match self.arg.opt_level {
|
|
|
|
None => (),
|
|
|
|
Some(level) => {
|
|
|
|
// fail hard if not succesful
|
2013-07-02 14:47:32 -05:00
|
|
|
assert!(((self.arg.fsync_fn)(&self.arg.val, level) != -1));
|
2013-03-20 20:18:57 -05:00
|
|
|
}
|
2012-06-21 23:30:16 -05:00
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-22 10:12:52 -06:00
|
|
|
pub struct Arg<t> {
|
2013-10-20 00:51:30 -05:00
|
|
|
priv val: t,
|
|
|
|
priv opt_level: Option<Level>,
|
|
|
|
priv fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
|
2013-01-22 10:12:52 -06:00
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
|
|
|
|
// fsync file after executing blk
|
2012-06-21 18:44:10 -05:00
|
|
|
// FIXME (#2004) find better way to create resources within lifetime of
|
|
|
|
// outer res
|
2013-09-10 20:57:24 -05:00
|
|
|
pub fn FILE_res_sync(file: &FILERes,
|
|
|
|
opt_level: Option<Level>,
|
2013-03-07 16:38:38 -06:00
|
|
|
blk: &fn(v: Res<*libc::FILE>)) {
|
2013-06-04 05:47:45 -05:00
|
|
|
blk(Res::new(Arg {
|
2013-09-10 20:57:24 -05:00
|
|
|
val: file.f,
|
|
|
|
opt_level: opt_level,
|
|
|
|
fsync_fn: fsync_FILE,
|
2013-04-09 00:31:23 -05:00
|
|
|
}));
|
2013-08-14 20:41:40 -05:00
|
|
|
|
|
|
|
fn fileno(stream: *libc::FILE) -> libc::c_int {
|
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
unsafe { libc::fileno(stream) }
|
|
|
|
}
|
2013-09-10 20:57:24 -05:00
|
|
|
|
|
|
|
fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
|
|
|
|
fsync_fd(fileno(*stream), level)
|
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// fsync fd after executing blk
|
2012-10-01 16:02:10 -05:00
|
|
|
pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
|
2013-03-07 16:38:38 -06:00
|
|
|
blk: &fn(v: Res<fd_t>)) {
|
2013-06-04 05:47:45 -05:00
|
|
|
blk(Res::new(Arg {
|
2013-09-10 20:57:24 -05:00
|
|
|
val: fd.fd,
|
|
|
|
opt_level: opt_level,
|
|
|
|
fsync_fn: fsync_fd_helper,
|
2011-11-16 16:14:18 -06:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2013-08-14 20:41:40 -05:00
|
|
|
fn fsync_fd(fd: libc::c_int, level: Level) -> int {
|
|
|
|
#[fixed_stack_segment]; #[inline(never)];
|
|
|
|
|
|
|
|
os::fsync_fd(fd, level) as int
|
|
|
|
}
|
|
|
|
|
2013-09-10 20:57:24 -05:00
|
|
|
fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
|
|
|
|
fsync_fd(*fd_ptr, level)
|
|
|
|
}
|
|
|
|
|
2011-11-16 16:14:18 -06:00
|
|
|
// Type of objects that may want to fsync
|
2012-12-24 12:52:53 -06:00
|
|
|
pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
|
2011-11-16 16:14:18 -06:00
|
|
|
|
|
|
|
// Call o.fsync after executing blk
|
2013-03-12 15:00:50 -05:00
|
|
|
pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
|
|
|
|
blk: &fn(v: Res<@FSyncable>)) {
|
2013-06-04 05:47:45 -05:00
|
|
|
blk(Res::new(Arg {
|
2013-09-10 20:57:24 -05:00
|
|
|
val: o,
|
|
|
|
opt_level: opt_level,
|
|
|
|
fsync_fn: obj_fsync_fn,
|
2011-11-16 16:14:18 -06:00
|
|
|
}));
|
|
|
|
}
|
2013-09-10 20:57:24 -05:00
|
|
|
|
|
|
|
fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
|
|
|
|
(*o).fsync(level)
|
|
|
|
}
|
2011-11-16 16:14:18 -06:00
|
|
|
}
|
2011-08-01 17:53:14 -05:00
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
2013-08-01 02:16:42 -05:00
|
|
|
use prelude::*;
|
2012-12-27 19:53:04 -06:00
|
|
|
use i32;
|
2013-01-08 21:37:25 -06:00
|
|
|
use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
|
2012-12-27 19:53:04 -06:00
|
|
|
use io;
|
2013-01-08 21:37:25 -06:00
|
|
|
use path::Path;
|
2013-07-24 22:23:38 -05:00
|
|
|
use result::{Ok, Err};
|
2012-12-27 19:53:04 -06:00
|
|
|
use u64;
|
|
|
|
use vec;
|
2013-09-03 18:24:12 -05:00
|
|
|
use cast::transmute;
|
2012-01-17 21:05:07 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_simple() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let tmpfile = &Path::new("tmp/lib-io-test-simple.tmp");
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{}", tmpfile.display());
|
2012-07-14 00:57:48 -05:00
|
|
|
let frood: ~str =
|
|
|
|
~"A hoopy frood who really knows where his towel is.";
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{}", frood.clone());
|
2012-01-17 21:05:07 -06:00
|
|
|
{
|
2013-07-22 19:27:53 -05:00
|
|
|
let out = io::file_writer(tmpfile, [io::Create, io::Truncate]).unwrap();
|
2012-01-17 21:05:07 -06:00
|
|
|
out.write_str(frood);
|
|
|
|
}
|
2013-07-22 19:27:53 -05:00
|
|
|
let inp = io::file_reader(tmpfile).unwrap();
|
2012-07-14 00:57:48 -05:00
|
|
|
let frood2: ~str = inp.read_c_str();
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("{}", frood2.clone());
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(frood, frood2);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2013-07-28 07:53:00 -05:00
|
|
|
#[test]
|
|
|
|
fn test_each_byte_each_char_file() {
|
|
|
|
// Issue #5056 -- shouldn't include trailing EOF.
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-each-byte-each-char-file.tmp");
|
2013-07-28 07:53:00 -05:00
|
|
|
|
|
|
|
{
|
|
|
|
// create empty, enough to reproduce a problem
|
|
|
|
io::file_writer(&path, [io::Create]).unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-07-31 14:07:44 -05:00
|
|
|
do file.each_byte() |_| {
|
2013-10-21 15:08:31 -05:00
|
|
|
fail!("must be empty")
|
2013-07-31 14:07:44 -05:00
|
|
|
};
|
2013-07-28 07:53:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-07-31 14:07:44 -05:00
|
|
|
do file.each_char() |_| {
|
2013-10-21 15:08:31 -05:00
|
|
|
fail!("must be empty")
|
2013-07-31 14:07:44 -05:00
|
|
|
};
|
2013-07-28 07:53:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
|
|
|
fn test_readchars_empty() {
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("") |inp| {
|
2012-09-28 23:51:14 -05:00
|
|
|
let res : ~[char] = inp.read_chars(128);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(res.len(), 0);
|
2012-08-21 20:32:23 -05:00
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
2013-01-28 21:32:02 -06:00
|
|
|
#[test]
|
|
|
|
fn test_read_line_utf8() {
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
|
2013-01-28 21:32:02 -06:00
|
|
|
let line = inp.read_line();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(line, ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
|
2013-01-28 21:32:02 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-14 01:41:28 -05:00
|
|
|
#[test]
|
|
|
|
fn test_read_lines() {
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("a\nb\nc\n") |inp| {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
|
2013-03-14 01:41:28 -05:00
|
|
|
}
|
|
|
|
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("a\nb\nc") |inp| {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
|
2013-03-14 01:41:28 -05:00
|
|
|
}
|
|
|
|
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("") |inp| {
|
2013-03-28 20:39:09 -05:00
|
|
|
assert!(inp.read_lines().is_empty());
|
2013-03-14 01:41:28 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
|
|
|
fn test_readchars_wide() {
|
2012-07-14 00:57:48 -05:00
|
|
|
let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
|
2012-06-29 18:26:56 -05:00
|
|
|
let ivals : ~[int] = ~[
|
2012-01-17 21:05:07 -06:00
|
|
|
29983, 38152, 30340, 27748,
|
|
|
|
21273, 20999, 32905, 27748,
|
|
|
|
104, 101, 108, 108, 111,
|
|
|
|
29983, 38152, 30340, 27748,
|
2012-06-29 18:26:56 -05:00
|
|
|
21273, 20999, 32905, 27748];
|
2012-09-28 23:51:14 -05:00
|
|
|
fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
|
2012-08-21 20:32:23 -05:00
|
|
|
do io::with_str_reader(s) |inp| {
|
|
|
|
let res : ~[char] = inp.read_chars(len);
|
2013-05-14 04:52:12 -05:00
|
|
|
if len <= ivals.len() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(res.len(), len);
|
2012-08-21 20:32:23 -05:00
|
|
|
}
|
2013-08-03 11:45:23 -05:00
|
|
|
for (iv, c) in ivals.iter().zip(res.iter()) {
|
2013-06-29 00:05:50 -05:00
|
|
|
assert!(*iv == *c as int)
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
}
|
2012-09-28 23:51:14 -05:00
|
|
|
let mut i = 0;
|
|
|
|
while i < 8 {
|
2012-01-17 21:05:07 -06:00
|
|
|
check_read_ln(i, wide_test, ivals);
|
2012-09-28 23:51:14 -05:00
|
|
|
i += 1;
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
// check a long read for good measure
|
2012-09-28 23:51:14 -05:00
|
|
|
check_read_ln(128, wide_test, ivals);
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_readchar() {
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("生") |inp| {
|
2013-09-03 18:24:12 -05:00
|
|
|
let res = inp.read_char();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(res as int, 29983);
|
2012-08-21 20:32:23 -05:00
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_readchar_empty() {
|
2013-05-23 11:39:17 -05:00
|
|
|
do io::with_str_reader("") |inp| {
|
2013-09-03 18:24:12 -05:00
|
|
|
let res = inp.read_char();
|
|
|
|
assert_eq!(res, unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
|
2012-08-21 20:32:23 -05:00
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn file_reader_not_exist() {
|
2013-10-05 21:49:32 -05:00
|
|
|
match io::file_reader(&Path::new("not a file")) {
|
2013-07-24 22:23:38 -05:00
|
|
|
Err(e) => {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(e, ~"error opening not a file");
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2013-10-21 15:08:31 -05:00
|
|
|
Ok(_) => fail!()
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-24 09:19:51 -06:00
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
|
|
|
fn test_read_buffer_too_small() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = &Path::new("tmp/lib-io-test-read-buffer-too-small.tmp");
|
2012-11-24 09:19:51 -06:00
|
|
|
// ensure the file exists
|
2013-07-11 14:05:17 -05:00
|
|
|
io::file_writer(path, [io::Create]).unwrap();
|
2012-11-24 09:19:51 -06:00
|
|
|
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(path).unwrap();
|
|
|
|
let mut buf = vec::from_elem(5, 0u8);
|
2012-11-24 09:19:51 -06:00
|
|
|
file.read(buf, 6); // this should fail because buf is too small
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_buffer_big_enough() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = &Path::new("tmp/lib-io-test-read-buffer-big-enough.tmp");
|
2012-11-24 09:19:51 -06:00
|
|
|
// ensure the file exists
|
2013-07-11 14:05:17 -05:00
|
|
|
io::file_writer(path, [io::Create]).unwrap();
|
2012-11-24 09:19:51 -06:00
|
|
|
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(path).unwrap();
|
|
|
|
let mut buf = vec::from_elem(5, 0u8);
|
2012-11-24 09:19:51 -06:00
|
|
|
file.read(buf, 4); // this should succeed because buf is big enough
|
|
|
|
}
|
|
|
|
|
2012-11-03 13:48:02 -05:00
|
|
|
#[test]
|
|
|
|
fn test_write_empty() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let file = io::file_writer(&Path::new("tmp/lib-io-test-write-empty.tmp"),
|
2013-07-11 14:05:17 -05:00
|
|
|
[io::Create]).unwrap();
|
2012-11-03 13:48:02 -05:00
|
|
|
file.write([]);
|
|
|
|
}
|
|
|
|
|
2012-01-17 21:05:07 -06:00
|
|
|
#[test]
|
|
|
|
fn file_writer_bad_name() {
|
2013-10-05 21:49:32 -05:00
|
|
|
match io::file_writer(&Path::new("?/?"), []) {
|
2013-07-24 22:23:38 -05:00
|
|
|
Err(e) => {
|
2013-06-10 10:03:16 -05:00
|
|
|
assert!(e.starts_with("error opening"));
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
2013-10-21 15:08:31 -05:00
|
|
|
Ok(_) => fail!()
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-11 12:44:57 -05:00
|
|
|
#[test]
|
2012-09-14 11:40:28 -05:00
|
|
|
fn bytes_buffer_overwrite() {
|
2013-06-04 05:47:45 -05:00
|
|
|
let wr = BytesWriter::new();
|
2013-05-23 11:39:17 -05:00
|
|
|
wr.write([0u8, 1u8, 2u8, 3u8]);
|
2013-05-07 19:57:58 -05:00
|
|
|
assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
|
2012-09-14 11:40:28 -05:00
|
|
|
wr.seek(-2, SeekCur);
|
2013-05-23 11:39:17 -05:00
|
|
|
wr.write([4u8, 5u8, 6u8, 7u8]);
|
2013-05-07 19:57:58 -05:00
|
|
|
assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
|
2012-09-14 11:40:28 -05:00
|
|
|
wr.seek(-2, SeekEnd);
|
2013-05-23 11:39:17 -05:00
|
|
|
wr.write([8u8]);
|
2012-09-14 11:40:28 -05:00
|
|
|
wr.seek(1, SeekSet);
|
2013-05-23 11:39:17 -05:00
|
|
|
wr.write([9u8]);
|
2013-05-07 19:57:58 -05:00
|
|
|
assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
|
2012-05-11 12:44:57 -05:00
|
|
|
}
|
2012-11-04 04:14:49 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_write_le() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-read-write-le.tmp");
|
2012-11-04 04:14:49 -06:00
|
|
|
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
|
|
|
|
|
|
|
|
// write the ints to the file
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_writer(&path, [io::Create]).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in uints.iter() {
|
2012-11-04 04:14:49 -06:00
|
|
|
file.write_le_u64(*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then read them back and check that they are the same
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in uints.iter() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(file.read_le_u64(), *i);
|
2012-11-04 04:14:49 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_write_be() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-read-write-be.tmp");
|
2012-11-04 04:14:49 -06:00
|
|
|
let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
|
|
|
|
|
|
|
|
// write the ints to the file
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_writer(&path, [io::Create]).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in uints.iter() {
|
2012-11-04 04:14:49 -06:00
|
|
|
file.write_be_u64(*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then read them back and check that they are the same
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in uints.iter() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(file.read_be_u64(), *i);
|
2012-11-04 04:14:49 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_be_int_n() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-read-be-int-n.tmp");
|
2012-11-04 04:14:49 -06:00
|
|
|
let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
|
|
|
|
|
|
|
|
// write the ints to the file
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_writer(&path, [io::Create]).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in ints.iter() {
|
2012-11-04 04:14:49 -06:00
|
|
|
file.write_be_i32(*i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then read them back and check that they are the same
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-08-03 11:45:23 -05:00
|
|
|
for i in ints.iter() {
|
2012-11-04 04:14:49 -06:00
|
|
|
// this tests that the sign extension is working
|
|
|
|
// (comparing the values as i32 would not test this)
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(file.read_be_int_n(4), *i as i64);
|
2012-11-04 04:14:49 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-05 18:07:04 -06:00
|
|
|
#[test]
|
|
|
|
fn test_read_f32() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-read-f32.tmp");
|
2013-03-05 18:07:04 -06:00
|
|
|
//big-endian floating-point 8.1250
|
|
|
|
let buf = ~[0x41, 0x02, 0x00, 0x00];
|
|
|
|
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_writer(&path, [io::Create]).unwrap();
|
2013-03-05 18:07:04 -06:00
|
|
|
file.write(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-03-05 18:07:04 -06:00
|
|
|
let f = file.read_be_f32();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(f, 8.1250);
|
2013-03-05 18:07:04 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-23 11:39:17 -05:00
|
|
|
#[test]
|
2013-03-05 18:07:04 -06:00
|
|
|
fn test_read_write_f32() {
|
2013-10-05 21:49:32 -05:00
|
|
|
let path = Path::new("tmp/lib-io-test-read-write-f32.tmp");
|
2013-03-05 18:07:04 -06:00
|
|
|
let f:f32 = 8.1250;
|
|
|
|
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_writer(&path, [io::Create]).unwrap();
|
2013-03-05 18:07:04 -06:00
|
|
|
file.write_be_f32(f);
|
|
|
|
file.write_le_f32(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2013-07-11 14:05:17 -05:00
|
|
|
let file = io::file_reader(&path).unwrap();
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(file.read_be_f32(), 8.1250);
|
|
|
|
assert_eq!(file.read_le_f32(), 8.1250);
|
2013-03-05 18:07:04 -06:00
|
|
|
}
|
|
|
|
}
|
2012-01-17 21:05:07 -06:00
|
|
|
}
|