rust/src/libstd/io/mod.rs
Alex Crichton 3369b33a20 rollup merge of #19902: alexcrichton/second-pass-mem
This commit stabilizes the `mem` and `default` modules of std.
2014-12-17 11:50:29 -08:00

2048 lines
67 KiB
Rust

// Copyright 2013-2014 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.
//
// ignore-lexer-test FIXME #15883
// FIXME: cover these topics:
// path, reader, writer, stream, raii (close not needed),
// stdio, print!, println!, file access, process spawning,
// error handling
//! I/O, including files, networking, timers, and processes
//!
//! `std::io` provides Rust's basic I/O types,
//! for reading and writing to files, TCP, UDP,
//! and other types of sockets and pipes,
//! manipulating the file system, spawning processes.
//!
//! # Examples
//!
//! Some examples of obvious things you might want to do
//!
//! * Read lines from stdin
//!
//! ```rust
//! use std::io;
//!
//! for line in io::stdin().lock().lines() {
//! print!("{}", line.unwrap());
//! }
//! ```
//!
//! * Read a complete file
//!
//! ```rust
//! use std::io::File;
//!
//! let contents = File::open(&Path::new("message.txt")).read_to_end();
//! ```
//!
//! * Write a line to a file
//!
//! ```rust
//! # #![allow(unused_must_use)]
//! use std::io::File;
//!
//! let mut file = File::create(&Path::new("message.txt"));
//! file.write(b"hello, file!\n");
//! # drop(file);
//! # ::std::io::fs::unlink(&Path::new("message.txt"));
//! ```
//!
//! * Iterate over the lines of a file
//!
//! ```rust,no_run
//! use std::io::BufferedReader;
//! use std::io::File;
//!
//! let path = Path::new("message.txt");
//! let mut file = BufferedReader::new(File::open(&path));
//! for line in file.lines() {
//! print!("{}", line.unwrap());
//! }
//! ```
//!
//! * Pull the lines of a file into a vector of strings
//!
//! ```rust,no_run
//! use std::io::BufferedReader;
//! use std::io::File;
//!
//! let path = Path::new("message.txt");
//! let mut file = BufferedReader::new(File::open(&path));
//! let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
//! ```
//!
//! * Make a simple TCP client connection and request
//!
//! ```rust
//! # #![allow(unused_must_use)]
//! use std::io::TcpStream;
//!
//! # // connection doesn't fail if a server is running on 8080
//! # // locally, we still want to be type checking this code, so lets
//! # // just stop it running (#11576)
//! # if false {
//! let mut socket = TcpStream::connect("127.0.0.1:8080").unwrap();
//! socket.write(b"GET / HTTP/1.0\n\n");
//! let response = socket.read_to_end();
//! # }
//! ```
//!
//! * Make a simple TCP server
//!
//! ```rust
//! # fn main() { }
//! # fn foo() {
//! # #![allow(dead_code)]
//! use std::io::{TcpListener, TcpStream};
//! use std::io::{Acceptor, Listener};
//!
//! let listener = TcpListener::bind("127.0.0.1:80");
//!
//! // bind the listener to the specified address
//! let mut acceptor = listener.listen();
//!
//! fn handle_client(mut stream: TcpStream) {
//! // ...
//! # &mut stream; // silence unused mutability/variable warning
//! }
//! // accept connections and process them, spawning a new tasks for each one
//! for stream in acceptor.incoming() {
//! match stream {
//! Err(e) => { /* connection failed */ }
//! Ok(stream) => spawn(move|| {
//! // connection succeeded
//! handle_client(stream)
//! })
//! }
//! }
//!
//! // close the socket server
//! drop(acceptor);
//! # }
//! ```
//!
//!
//! # Error Handling
//!
//! I/O is an area where nearly every operation can result in unexpected
//! errors. Errors should be painfully visible when they happen, and handling them
//! should be easy to work with. It should be convenient to handle specific I/O
//! errors, and it should also be convenient to not deal with I/O errors.
//!
//! Rust's I/O employs a combination of techniques to reduce boilerplate
//! while still providing feedback about errors. The basic strategy:
//!
//! * All I/O operations return `IoResult<T>` which is equivalent to
//! `Result<T, IoError>`. The `Result` type is defined in the `std::result`
//! module.
//! * If the `Result` type goes unused, then the compiler will by default emit a
//! warning about the unused result. This is because `Result` has the
//! `#[must_use]` attribute.
//! * Common traits are implemented for `IoResult`, e.g.
//! `impl<R: Reader> Reader for IoResult<R>`, so that error values do not have
//! to be 'unwrapped' before use.
//!
//! These features combine in the API to allow for expressions like
//! `File::create(&Path::new("diary.txt")).write(b"Met a girl.\n")`
//! without having to worry about whether "diary.txt" exists or whether
//! the write succeeds. As written, if either `new` or `write_line`
//! encounters an error then the result of the entire expression will
//! be an error.
//!
//! If you wanted to handle the error though you might write:
//!
//! ```rust
//! # #![allow(unused_must_use)]
//! use std::io::File;
//!
//! match File::create(&Path::new("diary.txt")).write(b"Met a girl.\n") {
//! Ok(()) => (), // succeeded
//! Err(e) => println!("failed to write to my diary: {}", e),
//! }
//!
//! # ::std::io::fs::unlink(&Path::new("diary.txt"));
//! ```
//!
//! So what actually happens if `create` encounters an error?
//! It's important to know that what `new` returns is not a `File`
//! but an `IoResult<File>`. If the file does not open, then `new` will simply
//! return `Err(..)`. Because there is an implementation of `Writer` (the trait
//! required ultimately required for types to implement `write_line`) there is no
//! need to inspect or unwrap the `IoResult<File>` and we simply call `write_line`
//! on it. If `new` returned an `Err(..)` then the followup call to `write_line`
//! will also return an error.
//!
//! ## `try!`
//!
//! Explicit pattern matching on `IoResult`s can get quite verbose, especially
//! when performing many I/O operations. Some examples (like those above) are
//! alleviated with extra methods implemented on `IoResult`, but others have more
//! complex interdependencies among each I/O operation.
//!
//! The `try!` macro from `std::macros` is provided as a method of early-return
//! inside `Result`-returning functions. It expands to an early-return on `Err`
//! and otherwise unwraps the contained `Ok` value.
//!
//! If you wanted to read several `u32`s from a file and return their product:
//!
//! ```rust
//! use std::io::{File, IoResult};
//!
//! fn file_product(p: &Path) -> IoResult<u32> {
//! let mut f = File::open(p);
//! let x1 = try!(f.read_le_u32());
//! let x2 = try!(f.read_le_u32());
//!
//! Ok(x1 * x2)
//! }
//!
//! match file_product(&Path::new("numbers.bin")) {
//! Ok(x) => println!("{}", x),
//! Err(e) => println!("Failed to read numbers!")
//! }
//! ```
//!
//! With `try!` in `file_product`, each `read_le_u32` need not be directly
//! concerned with error handling; instead its caller is responsible for
//! responding to errors that may occur while attempting to read the numbers.
#![experimental]
#![deny(unused_must_use)]
pub use self::SeekStyle::*;
pub use self::FileMode::*;
pub use self::FileAccess::*;
pub use self::IoErrorKind::*;
use char::Char;
use clone::Clone;
use default::Default;
use error::{FromError, Error};
use fmt;
use int;
use iter::{Iterator, IteratorExt};
use kinds::Copy;
use mem::transmute;
use ops::{BitOr, BitXor, BitAnd, Sub, Not, FnOnce};
use option::Option;
use option::Option::{Some, None};
use os;
use boxed::Box;
use result::Result;
use result::Result::{Ok, Err};
use sys;
use slice::SliceExt;
use str::StrPrelude;
use str;
use string::String;
use uint;
use unicode::char::UnicodeChar;
use vec::Vec;
// Reexports
pub use self::stdio::stdin;
pub use self::stdio::stdout;
pub use self::stdio::stderr;
pub use self::stdio::print;
pub use self::stdio::println;
pub use self::fs::File;
pub use self::timer::Timer;
pub use self::net::ip::IpAddr;
pub use self::net::tcp::TcpListener;
pub use self::net::tcp::TcpStream;
pub use self::net::udp::UdpStream;
pub use self::pipe::PipeStream;
pub use self::process::{Process, Command};
pub use self::tempfile::TempDir;
pub use self::mem::{MemReader, BufReader, MemWriter, BufWriter};
pub use self::buffered::{BufferedReader, BufferedWriter, BufferedStream,
LineBufferedWriter};
pub use self::comm_adapters::{ChanReader, ChanWriter};
mod buffered;
mod comm_adapters;
mod mem;
mod result;
mod tempfile;
pub mod extensions;
pub mod fs;
pub mod net;
pub mod pipe;
pub mod process;
pub mod stdio;
pub mod test;
pub mod timer;
pub mod util;
/// The default buffer size for various I/O operations
// libuv recommends 64k buffers to maximize throughput
// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
const DEFAULT_BUF_SIZE: uint = 1024 * 64;
/// A convenient typedef of the return value of any I/O action.
pub type IoResult<T> = Result<T, IoError>;
/// The type passed to I/O condition handlers to indicate error
///
/// # FIXME
///
/// Is something like this sufficient? It's kind of archaic
#[deriving(PartialEq, Eq, Clone)]
pub struct IoError {
/// An enumeration which can be matched against for determining the flavor
/// of error.
pub kind: IoErrorKind,
/// A human-readable description about the error
pub desc: &'static str,
/// Detailed information about this error, not always available
pub detail: Option<String>
}
impl IoError {
/// Convert an `errno` value into an `IoError`.
///
/// If `detail` is `true`, the `detail` field of the `IoError`
/// struct is filled with an allocated string describing the error
/// in more detail, retrieved from the operating system.
pub fn from_errno(errno: uint, detail: bool) -> IoError {
let mut err = sys::decode_error(errno as i32);
if detail && err.kind == OtherIoError {
err.detail = Some(os::error_string(errno).chars()
.map(|c| c.to_lowercase()).collect())
}
err
}
/// Retrieve the last error to occur as a (detailed) IoError.
///
/// This uses the OS `errno`, and so there should not be any task
/// descheduling or migration (other than that performed by the
/// operating system) between the call(s) for which errors are
/// being checked and the call of this function.
pub fn last_error() -> IoError {
IoError::from_errno(os::errno() as uint, true)
}
}
impl fmt::Show for IoError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
IoError { kind: OtherIoError, desc: "unknown error", detail: Some(ref detail) } =>
write!(fmt, "{}", detail),
IoError { detail: None, desc, .. } =>
write!(fmt, "{}", desc),
IoError { detail: Some(ref detail), desc, .. } =>
write!(fmt, "{} ({})", desc, detail)
}
}
}
impl Error for IoError {
fn description(&self) -> &str {
self.desc
}
fn detail(&self) -> Option<String> {
self.detail.clone()
}
}
impl FromError<IoError> for Box<Error> {
fn from_error(err: IoError) -> Box<Error> {
box err
}
}
/// A list specifying general categories of I/O error.
#[deriving(PartialEq, Eq, Clone, Show)]
pub enum IoErrorKind {
/// Any I/O error not part of this list.
OtherIoError,
/// The operation could not complete because end of file was reached.
EndOfFile,
/// The file was not found.
FileNotFound,
/// The file permissions disallowed access to this file.
PermissionDenied,
/// A network connection failed for some reason not specified in this list.
ConnectionFailed,
/// The network operation failed because the network connection was closed.
Closed,
/// The connection was refused by the remote server.
ConnectionRefused,
/// The connection was reset by the remote server.
ConnectionReset,
/// The connection was aborted (terminated) by the remote server.
ConnectionAborted,
/// The network operation failed because it was not connected yet.
NotConnected,
/// The operation failed because a pipe was closed.
BrokenPipe,
/// A file already existed with that name.
PathAlreadyExists,
/// No file exists at that location.
PathDoesntExist,
/// The path did not specify the type of file that this operation required. For example,
/// attempting to copy a directory with the `fs::copy()` operation will fail with this error.
MismatchedFileTypeForOperation,
/// The operation temporarily failed (for example, because a signal was received), and retrying
/// may succeed.
ResourceUnavailable,
/// No I/O functionality is available for this task.
IoUnavailable,
/// A parameter was incorrect in a way that caused an I/O error not part of this list.
InvalidInput,
/// The I/O operation's timeout expired, causing it to be canceled.
TimedOut,
/// This write operation failed to write all of its data.
///
/// Normally the write() method on a Writer guarantees that all of its data
/// has been written, but some operations may be terminated after only
/// partially writing some data. An example of this is a timed out write
/// which successfully wrote a known number of bytes, but bailed out after
/// doing so.
///
/// The payload contained as part of this variant is the number of bytes
/// which are known to have been successfully written.
ShortWrite(uint),
/// The Reader returned 0 bytes from `read()` too many times.
NoProgress,
}
impl Copy for IoErrorKind {}
/// A trait that lets you add a `detail` to an IoError easily
trait UpdateIoError<T> {
/// Returns an IoError with updated description and detail
fn update_err<D>(self, desc: &'static str, detail: D) -> Self where
D: FnOnce(&IoError) -> String;
/// Returns an IoError with updated detail
fn update_detail<D>(self, detail: D) -> Self where
D: FnOnce(&IoError) -> String;
/// Returns an IoError with update description
fn update_desc(self, desc: &'static str) -> Self;
}
impl<T> UpdateIoError<T> for IoResult<T> {
fn update_err<D>(self, desc: &'static str, detail: D) -> IoResult<T> where
D: FnOnce(&IoError) -> String,
{
self.map_err(move |mut e| {
let detail = detail(&e);
e.desc = desc;
e.detail = Some(detail);
e
})
}
fn update_detail<D>(self, detail: D) -> IoResult<T> where
D: FnOnce(&IoError) -> String,
{
self.map_err(move |mut e| { e.detail = Some(detail(&e)); e })
}
fn update_desc(self, desc: &'static str) -> IoResult<T> {
self.map_err(|mut e| { e.desc = desc; e })
}
}
static NO_PROGRESS_LIMIT: uint = 1000;
/// A trait for objects which are byte-oriented streams. Readers are defined by
/// one method, `read`. This function will block until data is available,
/// filling in the provided buffer with any data read.
///
/// Readers are intended to be composable with one another. Many objects
/// throughout the I/O and related libraries take and provide types which
/// implement the `Reader` trait.
pub trait Reader {
// Only method which need to get implemented for this trait
/// Read bytes, up to the length of `buf` and place them in `buf`.
/// Returns the number of bytes read. The number of bytes read may
/// be less than the number requested, even 0. Returns `Err` on EOF.
///
/// # Error
///
/// If an error occurs during this I/O operation, then it is returned as
/// `Err(IoError)`. Note that end-of-file is considered an error, and can be
/// inspected for in the error's `kind` field. Also note that reading 0
/// bytes is not considered an error in all circumstances
///
/// # Implementation Note
///
/// When implementing this method on a new Reader, you are strongly encouraged
/// not to return 0 if you can avoid it.
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
// Convenient helper methods based on the above methods
/// Reads at least `min` bytes and places them in `buf`.
/// Returns the number of bytes read.
///
/// This will continue to call `read` until at least `min` bytes have been
/// read. If `read` returns 0 too many times, `NoProgress` will be
/// returned.
///
/// # Error
///
/// If an error occurs at any point, that error is returned, and no further
/// bytes are read.
fn read_at_least(&mut self, min: uint, buf: &mut [u8]) -> IoResult<uint> {
if min > buf.len() {
return Err(IoError {
detail: Some(String::from_str("the buffer is too short")),
..standard_error(InvalidInput)
});
}
let mut read = 0;
while read < min {
let mut zeroes = 0;
loop {
match self.read(buf[mut read..]) {
Ok(0) => {
zeroes += 1;
if zeroes >= NO_PROGRESS_LIMIT {
return Err(standard_error(NoProgress));
}
}
Ok(n) => {
read += n;
break;
}
err@Err(_) => return err
}
}
}
Ok(read)
}
/// Reads a single byte. Returns `Err` on EOF.
fn read_byte(&mut self) -> IoResult<u8> {
let mut buf = [0];
try!(self.read_at_least(1, &mut buf));
Ok(buf[0])
}
/// Reads up to `len` bytes and appends them to a vector.
/// Returns the number of bytes read. The number of bytes read may be
/// less than the number requested, even 0. Returns Err on EOF.
///
/// # Error
///
/// If an error occurs during this I/O operation, then it is returned
/// as `Err(IoError)`. See `read()` for more details.
fn push(&mut self, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
let start_len = buf.len();
buf.reserve(len);
let n = {
let s = unsafe { slice_vec_capacity(buf, start_len, start_len + len) };
try!(self.read(s))
};
unsafe { buf.set_len(start_len + n) };
Ok(n)
}
/// Reads at least `min` bytes, but no more than `len`, and appends them to
/// a vector.
/// Returns the number of bytes read.
///
/// This will continue to call `read` until at least `min` bytes have been
/// read. If `read` returns 0 too many times, `NoProgress` will be
/// returned.
///
/// # Error
///
/// If an error occurs at any point, that error is returned, and no further
/// bytes are read.
fn push_at_least(&mut self, min: uint, len: uint, buf: &mut Vec<u8>) -> IoResult<uint> {
if min > len {
return Err(IoError {
detail: Some(String::from_str("the buffer is too short")),
..standard_error(InvalidInput)
});
}
let start_len = buf.len();
buf.reserve(len);
// we can't just use self.read_at_least(min, slice) because we need to push
// successful reads onto the vector before any returned errors.
let mut read = 0;
while read < min {
read += {
let s = unsafe { slice_vec_capacity(buf, start_len + read, start_len + len) };
try!(self.read_at_least(1, s))
};
unsafe { buf.set_len(start_len + read) };
}
Ok(read)
}
/// Reads exactly `len` bytes and gives you back a new vector of length
/// `len`
///
/// # Error
///
/// Fails with the same conditions as `read`. Additionally returns error
/// on EOF. Note that if an error is returned, then some number of bytes may
/// have already been consumed from the underlying reader, and they are lost
/// (not returned as part of the error). If this is unacceptable, then it is
/// recommended to use the `push_at_least` or `read` methods.
fn read_exact(&mut self, len: uint) -> IoResult<Vec<u8>> {
let mut buf = Vec::with_capacity(len);
match self.push_at_least(len, len, &mut buf) {
Ok(_) => Ok(buf),
Err(e) => Err(e),
}
}
/// Reads all remaining bytes from the stream.
///
/// # Error
///
/// Returns any non-EOF error immediately. Previously read bytes are
/// discarded when an error is returned.
///
/// When EOF is encountered, all bytes read up to that point are returned.
fn read_to_end(&mut self) -> IoResult<Vec<u8>> {
let mut buf = Vec::with_capacity(DEFAULT_BUF_SIZE);
loop {
match self.push_at_least(1, DEFAULT_BUF_SIZE, &mut buf) {
Ok(_) => {}
Err(ref e) if e.kind == EndOfFile => break,
Err(e) => return Err(e)
}
}
return Ok(buf);
}
/// Reads all of the remaining bytes of this stream, interpreting them as a
/// UTF-8 encoded stream. The corresponding string is returned.
///
/// # Error
///
/// This function returns all of the same errors as `read_to_end` with an
/// additional error if the reader's contents are not a valid sequence of
/// UTF-8 bytes.
fn read_to_string(&mut self) -> IoResult<String> {
self.read_to_end().and_then(|s| {
match String::from_utf8(s) {
Ok(s) => Ok(s),
Err(_) => Err(standard_error(InvalidInput)),
}
})
}
// Byte conversion helpers
/// Reads `n` little-endian unsigned integer bytes.
///
/// `n` must be between 1 and 8, inclusive.
fn read_le_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
assert!(nbytes > 0 && nbytes <= 8);
let mut val = 0u64;
let mut pos = 0;
let mut i = nbytes;
while i > 0 {
val += (try!(self.read_u8()) as u64) << pos;
pos += 8;
i -= 1;
}
Ok(val)
}
/// Reads `n` little-endian signed integer bytes.
///
/// `n` must be between 1 and 8, inclusive.
fn read_le_int_n(&mut self, nbytes: uint) -> IoResult<i64> {
self.read_le_uint_n(nbytes).map(|i| extend_sign(i, nbytes))
}
/// Reads `n` big-endian unsigned integer bytes.
///
/// `n` must be between 1 and 8, inclusive.
fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
assert!(nbytes > 0 && nbytes <= 8);
let mut val = 0u64;
let mut i = nbytes;
while i > 0 {
i -= 1;
val += (try!(self.read_u8()) as u64) << i * 8;
}
Ok(val)
}
/// Reads `n` big-endian signed integer bytes.
///
/// `n` must be between 1 and 8, inclusive.
fn read_be_int_n(&mut self, nbytes: uint) -> IoResult<i64> {
self.read_be_uint_n(nbytes).map(|i| extend_sign(i, nbytes))
}
/// Reads a little-endian unsigned integer.
///
/// The number of bytes returned is system-dependent.
fn read_le_uint(&mut self) -> IoResult<uint> {
self.read_le_uint_n(uint::BYTES).map(|i| i as uint)
}
/// Reads a little-endian integer.
///
/// The number of bytes returned is system-dependent.
fn read_le_int(&mut self) -> IoResult<int> {
self.read_le_int_n(int::BYTES).map(|i| i as int)
}
/// Reads a big-endian unsigned integer.
///
/// The number of bytes returned is system-dependent.
fn read_be_uint(&mut self) -> IoResult<uint> {
self.read_be_uint_n(uint::BYTES).map(|i| i as uint)
}
/// Reads a big-endian integer.
///
/// The number of bytes returned is system-dependent.
fn read_be_int(&mut self) -> IoResult<int> {
self.read_be_int_n(int::BYTES).map(|i| i as int)
}
/// Reads a big-endian `u64`.
///
/// `u64`s are 8 bytes long.
fn read_be_u64(&mut self) -> IoResult<u64> {
self.read_be_uint_n(8)
}
/// Reads a big-endian `u32`.
///
/// `u32`s are 4 bytes long.
fn read_be_u32(&mut self) -> IoResult<u32> {
self.read_be_uint_n(4).map(|i| i as u32)
}
/// Reads a big-endian `u16`.
///
/// `u16`s are 2 bytes long.
fn read_be_u16(&mut self) -> IoResult<u16> {
self.read_be_uint_n(2).map(|i| i as u16)
}
/// Reads a big-endian `i64`.
///
/// `i64`s are 8 bytes long.
fn read_be_i64(&mut self) -> IoResult<i64> {
self.read_be_int_n(8)
}
/// Reads a big-endian `i32`.
///
/// `i32`s are 4 bytes long.
fn read_be_i32(&mut self) -> IoResult<i32> {
self.read_be_int_n(4).map(|i| i as i32)
}
/// Reads a big-endian `i16`.
///
/// `i16`s are 2 bytes long.
fn read_be_i16(&mut self) -> IoResult<i16> {
self.read_be_int_n(2).map(|i| i as i16)
}
/// Reads a big-endian `f64`.
///
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
fn read_be_f64(&mut self) -> IoResult<f64> {
self.read_be_u64().map(|i| unsafe {
transmute::<u64, f64>(i)
})
}
/// Reads a big-endian `f32`.
///
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
fn read_be_f32(&mut self) -> IoResult<f32> {
self.read_be_u32().map(|i| unsafe {
transmute::<u32, f32>(i)
})
}
/// Reads a little-endian `u64`.
///
/// `u64`s are 8 bytes long.
fn read_le_u64(&mut self) -> IoResult<u64> {
self.read_le_uint_n(8)
}
/// Reads a little-endian `u32`.
///
/// `u32`s are 4 bytes long.
fn read_le_u32(&mut self) -> IoResult<u32> {
self.read_le_uint_n(4).map(|i| i as u32)
}
/// Reads a little-endian `u16`.
///
/// `u16`s are 2 bytes long.
fn read_le_u16(&mut self) -> IoResult<u16> {
self.read_le_uint_n(2).map(|i| i as u16)
}
/// Reads a little-endian `i64`.
///
/// `i64`s are 8 bytes long.
fn read_le_i64(&mut self) -> IoResult<i64> {
self.read_le_int_n(8)
}
/// Reads a little-endian `i32`.
///
/// `i32`s are 4 bytes long.
fn read_le_i32(&mut self) -> IoResult<i32> {
self.read_le_int_n(4).map(|i| i as i32)
}
/// Reads a little-endian `i16`.
///
/// `i16`s are 2 bytes long.
fn read_le_i16(&mut self) -> IoResult<i16> {
self.read_le_int_n(2).map(|i| i as i16)
}
/// Reads a little-endian `f64`.
///
/// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
fn read_le_f64(&mut self) -> IoResult<f64> {
self.read_le_u64().map(|i| unsafe {
transmute::<u64, f64>(i)
})
}
/// Reads a little-endian `f32`.
///
/// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
fn read_le_f32(&mut self) -> IoResult<f32> {
self.read_le_u32().map(|i| unsafe {
transmute::<u32, f32>(i)
})
}
/// Read a u8.
///
/// `u8`s are 1 byte.
fn read_u8(&mut self) -> IoResult<u8> {
self.read_byte()
}
/// Read an i8.
///
/// `i8`s are 1 byte.
fn read_i8(&mut self) -> IoResult<i8> {
self.read_byte().map(|i| i as i8)
}
}
/// A reader which can be converted to a RefReader.
#[deprecated = "use ByRefReader instead"]
pub trait AsRefReader {
/// Creates a wrapper around a mutable reference to the reader.
///
/// This is useful to allow applying adaptors while still
/// retaining ownership of the original value.
fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self>;
}
#[allow(deprecated)]
impl<T: Reader> AsRefReader for T {
fn by_ref<'a>(&'a mut self) -> RefReader<'a, T> {
RefReader { inner: self }
}
}
/// A reader which can be converted to a RefReader.
pub trait ByRefReader {
/// Creates a wrapper around a mutable reference to the reader.
///
/// This is useful to allow applying adaptors while still
/// retaining ownership of the original value.
fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self>;
}
impl<T: Reader> ByRefReader for T {
fn by_ref<'a>(&'a mut self) -> RefReader<'a, T> {
RefReader { inner: self }
}
}
/// A reader which can be converted to bytes.
pub trait BytesReader {
/// Create an iterator that reads a single byte on
/// each iteration, until EOF.
///
/// # Error
///
/// Any error other than `EndOfFile` that is produced by the underlying Reader
/// is returned by the iterator and should be handled by the caller.
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self>;
}
impl<T: Reader> BytesReader for T {
fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, T> {
extensions::Bytes::new(self)
}
}
impl<'a> Reader for Box<Reader+'a> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let reader: &mut Reader = &mut **self;
reader.read(buf)
}
}
impl<'a> Reader for &'a mut (Reader+'a) {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { (*self).read(buf) }
}
/// Returns a slice of `v` between `start` and `end`.
///
/// Similar to `slice()` except this function only bounds the slice on the
/// capacity of `v`, not the length.
///
/// # Panics
///
/// Panics when `start` or `end` point outside the capacity of `v`, or when
/// `start` > `end`.
// Private function here because we aren't sure if we want to expose this as
// API yet. If so, it should be a method on Vec.
unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -> &'a mut [T] {
use raw::Slice;
use ptr::RawPtr;
assert!(start <= end);
assert!(end <= v.capacity());
transmute(Slice {
data: v.as_ptr().offset(start as int),
len: end - start
})
}
/// A `RefReader` is a struct implementing `Reader` which contains a reference
/// to another reader. This is often useful when composing streams.
///
/// # Example
///
/// ```
/// # fn main() {}
/// # fn process_input<R: Reader>(r: R) {}
/// # fn foo() {
/// use std::io;
/// use std::io::ByRefReader;
/// use std::io::util::LimitReader;
///
/// let mut stream = io::stdin();
///
/// // Only allow the function to process at most one kilobyte of input
/// {
/// let stream = LimitReader::new(stream.by_ref(), 1024);
/// process_input(stream);
/// }
///
/// // 'stream' is still available for use here
///
/// # }
/// ```
pub struct RefReader<'a, R:'a> {
/// The underlying reader which this is referencing
inner: &'a mut R
}
impl<'a, R: Reader> Reader for RefReader<'a, R> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { self.inner.read(buf) }
}
impl<'a, R: Buffer> Buffer for RefReader<'a, R> {
fn fill_buf(&mut self) -> IoResult<&[u8]> { self.inner.fill_buf() }
fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
}
fn extend_sign(val: u64, nbytes: uint) -> i64 {
let shift = (8 - nbytes) * 8;
(val << shift) as i64 >> shift
}
/// A trait for objects which are byte-oriented streams. Writers are defined by
/// one method, `write`. This function will block until the provided buffer of
/// bytes has been entirely written, and it will return any failures which occur.
///
/// Another commonly overridden method is the `flush` method for writers such as
/// buffered writers.
///
/// Writers are intended to be composable with one another. Many objects
/// throughout the I/O and related libraries take and provide types which
/// implement the `Writer` trait.
pub trait Writer {
/// Write the entirety of a given buffer
///
/// # Errors
///
/// If an error happens during the I/O operation, the error is returned as
/// `Err`. Note that it is considered an error if the entire buffer could
/// not be written, and if an error is returned then it is unknown how much
/// data (if any) was actually written.
fn write(&mut self, buf: &[u8]) -> IoResult<()>;
/// Flush this output stream, ensuring that all intermediately buffered
/// contents reach their destination.
///
/// This is by default a no-op and implementers of the `Writer` trait should
/// decide whether their stream needs to be buffered or not.
fn flush(&mut self) -> IoResult<()> { Ok(()) }
/// Writes a formatted string into this writer, returning any error
/// encountered.
///
/// This method is primarily used to interface with the `format_args!`
/// macro, but it is rare that this should explicitly be called. The
/// `write!` macro should be favored to invoke this method instead.
///
/// # Errors
///
/// This function will return any I/O error reported while formatting.
fn write_fmt(&mut self, fmt: &fmt::Arguments) -> IoResult<()> {
// Create a shim which translates a Writer to a FormatWriter and saves
// off I/O errors. instead of discarding them
struct Adaptor<'a, T:'a> {
inner: &'a mut T,
error: IoResult<()>,
}
impl<'a, T: Writer> fmt::FormatWriter for Adaptor<'a, T> {
fn write(&mut self, bytes: &[u8]) -> fmt::Result {
match self.inner.write(bytes) {
Ok(()) => Ok(()),
Err(e) => {
self.error = Err(e);
Err(fmt::Error)
}
}
}
}
let mut output = Adaptor { inner: self, error: Ok(()) };
match fmt::write(&mut output, fmt) {
Ok(()) => Ok(()),
Err(..) => output.error
}
}
/// Write a rust string into this sink.
///
/// The bytes written will be the UTF-8 encoded version of the input string.
/// If other encodings are desired, it is recommended to compose this stream
/// with another performing the conversion, or to use `write` with a
/// converted byte-array instead.
#[inline]
fn write_str(&mut self, s: &str) -> IoResult<()> {
self.write(s.as_bytes())
}
/// Writes a string into this sink, and then writes a literal newline (`\n`)
/// byte afterwards. Note that the writing of the newline is *not* atomic in
/// the sense that the call to `write` is invoked twice (once with the
/// string and once with a newline character).
///
/// If other encodings or line ending flavors are desired, it is recommended
/// that the `write` method is used specifically instead.
#[inline]
fn write_line(&mut self, s: &str) -> IoResult<()> {
self.write_str(s).and_then(|()| self.write(&[b'\n']))
}
/// Write a single char, encoded as UTF-8.
#[inline]
fn write_char(&mut self, c: char) -> IoResult<()> {
let mut buf = [0u8, ..4];
let n = c.encode_utf8(buf[mut]).unwrap_or(0);
self.write(buf[..n])
}
/// Write the result of passing n through `int::to_str_bytes`.
#[inline]
fn write_int(&mut self, n: int) -> IoResult<()> {
write!(self, "{}", n)
}
/// Write the result of passing n through `uint::to_str_bytes`.
#[inline]
fn write_uint(&mut self, n: uint) -> IoResult<()> {
write!(self, "{}", n)
}
/// Write a little-endian uint (number of bytes depends on system).
#[inline]
fn write_le_uint(&mut self, n: uint) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, uint::BYTES, |v| self.write(v))
}
/// Write a little-endian int (number of bytes depends on system).
#[inline]
fn write_le_int(&mut self, n: int) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, int::BYTES, |v| self.write(v))
}
/// Write a big-endian uint (number of bytes depends on system).
#[inline]
fn write_be_uint(&mut self, n: uint) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, uint::BYTES, |v| self.write(v))
}
/// Write a big-endian int (number of bytes depends on system).
#[inline]
fn write_be_int(&mut self, n: int) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, int::BYTES, |v| self.write(v))
}
/// Write a big-endian u64 (8 bytes).
#[inline]
fn write_be_u64(&mut self, n: u64) -> IoResult<()> {
extensions::u64_to_be_bytes(n, 8u, |v| self.write(v))
}
/// Write a big-endian u32 (4 bytes).
#[inline]
fn write_be_u32(&mut self, n: u32) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
}
/// Write a big-endian u16 (2 bytes).
#[inline]
fn write_be_u16(&mut self, n: u16) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
}
/// Write a big-endian i64 (8 bytes).
#[inline]
fn write_be_i64(&mut self, n: i64) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
}
/// Write a big-endian i32 (4 bytes).
#[inline]
fn write_be_i32(&mut self, n: i32) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
}
/// Write a big-endian i16 (2 bytes).
#[inline]
fn write_be_i16(&mut self, n: i16) -> IoResult<()> {
extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
}
/// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
#[inline]
fn write_be_f64(&mut self, f: f64) -> IoResult<()> {
unsafe {
self.write_be_u64(transmute(f))
}
}
/// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
#[inline]
fn write_be_f32(&mut self, f: f32) -> IoResult<()> {
unsafe {
self.write_be_u32(transmute(f))
}
}
/// Write a little-endian u64 (8 bytes).
#[inline]
fn write_le_u64(&mut self, n: u64) -> IoResult<()> {
extensions::u64_to_le_bytes(n, 8u, |v| self.write(v))
}
/// Write a little-endian u32 (4 bytes).
#[inline]
fn write_le_u32(&mut self, n: u32) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
}
/// Write a little-endian u16 (2 bytes).
#[inline]
fn write_le_u16(&mut self, n: u16) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
}
/// Write a little-endian i64 (8 bytes).
#[inline]
fn write_le_i64(&mut self, n: i64) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
}
/// Write a little-endian i32 (4 bytes).
#[inline]
fn write_le_i32(&mut self, n: i32) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
}
/// Write a little-endian i16 (2 bytes).
#[inline]
fn write_le_i16(&mut self, n: i16) -> IoResult<()> {
extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
}
/// Write a little-endian IEEE754 double-precision floating-point
/// (8 bytes).
#[inline]
fn write_le_f64(&mut self, f: f64) -> IoResult<()> {
unsafe {
self.write_le_u64(transmute(f))
}
}
/// Write a little-endian IEEE754 single-precision floating-point
/// (4 bytes).
#[inline]
fn write_le_f32(&mut self, f: f32) -> IoResult<()> {
unsafe {
self.write_le_u32(transmute(f))
}
}
/// Write a u8 (1 byte).
#[inline]
fn write_u8(&mut self, n: u8) -> IoResult<()> {
self.write(&[n])
}
/// Write an i8 (1 byte).
#[inline]
fn write_i8(&mut self, n: i8) -> IoResult<()> {
self.write(&[n as u8])
}
}
/// A writer which can be converted to a RefWriter.
#[deprecated = "use ByRefWriter instead"]
pub trait AsRefWriter {
/// Creates a wrapper around a mutable reference to the writer.
///
/// This is useful to allow applying wrappers while still
/// retaining ownership of the original value.
#[inline]
fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self>;
}
#[allow(deprecated)]
impl<T: Writer> AsRefWriter for T {
fn by_ref<'a>(&'a mut self) -> RefWriter<'a, T> {
RefWriter { inner: self }
}
}
/// A writer which can be converted to a RefWriter.
pub trait ByRefWriter {
/// Creates a wrapper around a mutable reference to the writer.
///
/// This is useful to allow applying wrappers while still
/// retaining ownership of the original value.
#[inline]
fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self>;
}
impl<T: Writer> ByRefWriter for T {
fn by_ref<'a>(&'a mut self) -> RefWriter<'a, T> {
RefWriter { inner: self }
}
}
impl<'a> Writer for Box<Writer+'a> {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
(&mut **self).write(buf)
}
#[inline]
fn flush(&mut self) -> IoResult<()> {
(&mut **self).flush()
}
}
impl<'a> Writer for &'a mut (Writer+'a) {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> { (**self).write(buf) }
#[inline]
fn flush(&mut self) -> IoResult<()> { (**self).flush() }
}
/// A `RefWriter` is a struct implementing `Writer` which contains a reference
/// to another writer. This is often useful when composing streams.
///
/// # Example
///
/// ```
/// # fn main() {}
/// # fn process_input<R: Reader>(r: R) {}
/// # fn foo () {
/// use std::io::util::TeeReader;
/// use std::io::{stdin, ByRefWriter};
///
/// let mut output = Vec::new();
///
/// {
/// // Don't give ownership of 'output' to the 'tee'. Instead we keep a
/// // handle to it in the outer scope
/// let mut tee = TeeReader::new(stdin(), output.by_ref());
/// process_input(tee);
/// }
///
/// println!("input processed: {}", output);
/// # }
/// ```
pub struct RefWriter<'a, W:'a> {
/// The underlying writer which this is referencing
inner: &'a mut W
}
impl<'a, W: Writer> Writer for RefWriter<'a, W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> IoResult<()> { self.inner.write(buf) }
#[inline]
fn flush(&mut self) -> IoResult<()> { self.inner.flush() }
}
/// A Stream is a readable and a writable object. Data written is typically
/// received by the object which reads receive data from.
pub trait Stream: Reader + Writer { }
impl<T: Reader + Writer> Stream for T {}
/// An iterator that reads a line on each iteration,
/// until `.read_line()` encounters `EndOfFile`.
///
/// # Notes about the Iteration Protocol
///
/// The `Lines` may yield `None` and thus terminate
/// an iteration, but continue to yield elements if iteration
/// is attempted again.
///
/// # Error
///
/// Any error other than `EndOfFile` that is produced by the underlying Reader
/// is returned by the iterator and should be handled by the caller.
pub struct Lines<'r, T:'r> {
buffer: &'r mut T,
}
impl<'r, T: Buffer> Iterator<IoResult<String>> for Lines<'r, T> {
fn next(&mut self) -> Option<IoResult<String>> {
match self.buffer.read_line() {
Ok(x) => Some(Ok(x)),
Err(IoError { kind: EndOfFile, ..}) => None,
Err(y) => Some(Err(y))
}
}
}
/// An iterator that reads a utf8-encoded character on each iteration,
/// until `.read_char()` encounters `EndOfFile`.
///
/// # Notes about the Iteration Protocol
///
/// The `Chars` may yield `None` and thus terminate
/// an iteration, but continue to yield elements if iteration
/// is attempted again.
///
/// # Error
///
/// Any error other than `EndOfFile` that is produced by the underlying Reader
/// is returned by the iterator and should be handled by the caller.
pub struct Chars<'r, T:'r> {
buffer: &'r mut T
}
impl<'r, T: Buffer> Iterator<IoResult<char>> for Chars<'r, T> {
fn next(&mut self) -> Option<IoResult<char>> {
match self.buffer.read_char() {
Ok(x) => Some(Ok(x)),
Err(IoError { kind: EndOfFile, ..}) => None,
Err(y) => Some(Err(y))
}
}
}
/// A Buffer is a type of reader which has some form of internal buffering to
/// allow certain kinds of reading operations to be more optimized than others.
/// This type extends the `Reader` trait with a few methods that are not
/// possible to reasonably implement with purely a read interface.
pub trait Buffer: Reader {
/// Fills the internal buffer of this object, returning the buffer contents.
/// Note that none of the contents will be "read" in the sense that later
/// calling `read` may return the same contents.
///
/// The `consume` function must be called with the number of bytes that are
/// consumed from this buffer returned to ensure that the bytes are never
/// returned twice.
///
/// # Error
///
/// This function will return an I/O error if the underlying reader was
/// read, but returned an error. Note that it is not an error to return a
/// 0-length buffer.
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]>;
/// Tells this buffer that `amt` bytes have been consumed from the buffer,
/// so they should no longer be returned in calls to `read`.
fn consume(&mut self, amt: uint);
/// Reads the next line of input, interpreted as a sequence of UTF-8
/// encoded Unicode codepoints. If a newline is encountered, then the
/// newline is contained in the returned string.
///
/// # Example
///
/// ```rust
/// use std::io::BufReader;
///
/// let mut reader = BufReader::new(b"hello\nworld");
/// assert_eq!("hello\n", &*reader.read_line().unwrap());
/// ```
///
/// # Error
///
/// This function has the same error semantics as `read_until`:
///
/// * All non-EOF errors will be returned immediately
/// * If an error is returned previously consumed bytes are lost
/// * EOF is only returned if no bytes have been read
/// * Reach EOF may mean that the delimiter is not present in the return
/// value
///
/// Additionally, this function can fail if the line of input read is not a
/// valid UTF-8 sequence of bytes.
fn read_line(&mut self) -> IoResult<String> {
self.read_until(b'\n').and_then(|line|
match String::from_utf8(line) {
Ok(s) => Ok(s),
Err(_) => Err(standard_error(InvalidInput)),
}
)
}
/// Reads a sequence of bytes leading up to a specified delimiter. Once the
/// specified byte is encountered, reading ceases and the bytes up to and
/// including the delimiter are returned.
///
/// # Error
///
/// If any I/O error is encountered other than EOF, the error is immediately
/// returned. Note that this may discard bytes which have already been read,
/// and those bytes will *not* be returned. It is recommended to use other
/// methods if this case is worrying.
///
/// If EOF is encountered, then this function will return EOF if 0 bytes
/// have been read, otherwise the pending byte buffer is returned. This
/// is the reason that the byte buffer returned may not always contain the
/// delimiter.
fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
let mut res = Vec::new();
let mut used;
loop {
{
let available = match self.fill_buf() {
Ok(n) => n,
Err(ref e) if res.len() > 0 && e.kind == EndOfFile => {
used = 0;
break
}
Err(e) => return Err(e)
};
match available.iter().position(|&b| b == byte) {
Some(i) => {
res.push_all(available[..i + 1]);
used = i + 1;
break
}
None => {
res.push_all(available);
used = available.len();
}
}
}
self.consume(used);
}
self.consume(used);
Ok(res)
}
/// Reads the next utf8-encoded character from the underlying stream.
///
/// # Error
///
/// If an I/O error occurs, or EOF, then this function will return `Err`.
/// This function will also return error if the stream does not contain a
/// valid utf-8 encoded codepoint as the next few bytes in the stream.
fn read_char(&mut self) -> IoResult<char> {
let first_byte = try!(self.read_byte());
let width = str::utf8_char_width(first_byte);
if width == 1 { return Ok(first_byte as char) }
if width == 0 { return Err(standard_error(InvalidInput)) } // not utf8
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;
while start < width {
match try!(self.read(buf[mut start..width])) {
n if n == width - start => break,
n if n < width - start => { start += n; }
_ => return Err(standard_error(InvalidInput)),
}
}
}
match str::from_utf8(buf[..width]) {
Some(s) => Ok(s.char_at(0)),
None => Err(standard_error(InvalidInput))
}
}
}
/// Extension methods for the Buffer trait which are included in the prelude.
pub trait BufferPrelude {
/// Create an iterator that reads a utf8-encoded character on each iteration
/// until EOF.
///
/// # Error
///
/// Any error other than `EndOfFile` that is produced by the underlying Reader
/// is returned by the iterator and should be handled by the caller.
fn chars<'r>(&'r mut self) -> Chars<'r, Self>;
/// Create an iterator that reads a line on each iteration until EOF.
///
/// # Error
///
/// Any error other than `EndOfFile` that is produced by the underlying Reader
/// is returned by the iterator and should be handled by the caller.
fn lines<'r>(&'r mut self) -> Lines<'r, Self>;
}
impl<T: Buffer> BufferPrelude for T {
fn chars<'r>(&'r mut self) -> Chars<'r, T> {
Chars { buffer: self }
}
fn lines<'r>(&'r mut self) -> Lines<'r, T> {
Lines { buffer: self }
}
}
/// When seeking, the resulting cursor is offset from a base by the offset given
/// to the `seek` function. The base used is specified by this enumeration.
pub enum SeekStyle {
/// Seek from the beginning of the stream
SeekSet,
/// Seek from the end of the stream
SeekEnd,
/// Seek from the current position
SeekCur,
}
impl Copy for SeekStyle {}
/// An object implementing `Seek` internally has some form of cursor which can
/// be moved within a stream of bytes. The stream typically has a fixed size,
/// allowing seeking relative to either end.
pub trait Seek {
/// Return position of file cursor in the stream
fn tell(&self) -> IoResult<u64>;
/// Seek to an offset in a stream
///
/// A successful seek clears the EOF indicator. Seeking beyond EOF is
/// allowed, but seeking before position 0 is not allowed.
///
/// # Errors
///
/// * Seeking to a negative offset is considered an error
/// * Seeking past the end of the stream does not modify the underlying
/// stream, but the next write may cause the previous data to be filled in
/// with a bit pattern.
fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()>;
}
/// A listener is a value that can consume itself to start listening for
/// connections.
///
/// Doing so produces some sort of Acceptor.
pub trait Listener<T, A: Acceptor<T>> {
/// Spin up the listener and start queuing incoming connections
///
/// # Error
///
/// Returns `Err` if this listener could not be bound to listen for
/// connections. In all cases, this listener is consumed.
fn listen(self) -> IoResult<A>;
}
/// An acceptor is a value that presents incoming connections
pub trait Acceptor<T> {
/// Wait for and accept an incoming connection
///
/// # Error
///
/// Returns `Err` if an I/O error is encountered.
fn accept(&mut self) -> IoResult<T>;
/// Create an iterator over incoming connection attempts.
///
/// Note that I/O errors will be yielded by the iterator itself.
fn incoming<'r>(&'r mut self) -> IncomingConnections<'r, Self> {
IncomingConnections { inc: self }
}
}
/// An infinite iterator over incoming connection attempts.
/// Calling `next` will block the task until a connection is attempted.
///
/// Since connection attempts can continue forever, this iterator always returns
/// `Some`. The `Some` contains the `IoResult` representing whether the
/// connection attempt was successful. A successful connection will be wrapped
/// in `Ok`. A failed connection is represented as an `Err`.
pub struct IncomingConnections<'a, A:'a> {
inc: &'a mut A,
}
impl<'a, T, A: Acceptor<T>> Iterator<IoResult<T>> for IncomingConnections<'a, A> {
fn next(&mut self) -> Option<IoResult<T>> {
Some(self.inc.accept())
}
}
/// Creates a standard error for a commonly used flavor of error. The `detail`
/// field of the returned error will always be `None`.
///
/// # Example
///
/// ```
/// use std::io;
///
/// let eof = io::standard_error(io::EndOfFile);
/// let einval = io::standard_error(io::InvalidInput);
/// ```
pub fn standard_error(kind: IoErrorKind) -> IoError {
let desc = match kind {
EndOfFile => "end of file",
IoUnavailable => "I/O is unavailable",
InvalidInput => "invalid input",
OtherIoError => "unknown I/O error",
FileNotFound => "file not found",
PermissionDenied => "permission denied",
ConnectionFailed => "connection failed",
Closed => "stream is closed",
ConnectionRefused => "connection refused",
ConnectionReset => "connection reset",
ConnectionAborted => "connection aborted",
NotConnected => "not connected",
BrokenPipe => "broken pipe",
PathAlreadyExists => "file already exists",
PathDoesntExist => "no such file",
MismatchedFileTypeForOperation => "mismatched file type",
ResourceUnavailable => "resource unavailable",
TimedOut => "operation timed out",
ShortWrite(..) => "short write",
NoProgress => "no progress",
};
IoError {
kind: kind,
desc: desc,
detail: None,
}
}
/// A mode specifies how a file should be opened or created. These modes are
/// passed to `File::open_mode` and are used to control where the file is
/// positioned when it is initially opened.
pub enum FileMode {
/// Opens a file positioned at the beginning.
Open,
/// Opens a file positioned at EOF.
Append,
/// Opens a file, truncating it if it already exists.
Truncate,
}
impl Copy for FileMode {}
/// Access permissions with which the file should be opened. `File`s
/// opened with `Read` will return an error if written to.
pub enum FileAccess {
/// Read-only access, requests to write will result in an error
Read,
/// Write-only access, requests to read will result in an error
Write,
/// Read-write access, no requests are denied by default
ReadWrite,
}
impl Copy for FileAccess {}
/// Different kinds of files which can be identified by a call to stat
#[deriving(PartialEq, Show, Hash, Clone)]
pub enum FileType {
/// This is a normal file, corresponding to `S_IFREG`
RegularFile,
/// This file is a directory, corresponding to `S_IFDIR`
Directory,
/// This file is a named pipe, corresponding to `S_IFIFO`
NamedPipe,
/// This file is a block device, corresponding to `S_IFBLK`
BlockSpecial,
/// This file is a symbolic link to another file, corresponding to `S_IFLNK`
Symlink,
/// The type of this file is not recognized as one of the other categories
Unknown,
}
impl Copy for FileType {}
/// A structure used to describe metadata information about a file. This
/// structure is created through the `stat` method on a `Path`.
///
/// # Example
///
/// ```
/// # use std::io::fs::PathExtensions;
/// # fn main() {}
/// # fn foo() {
/// let info = match Path::new("foo.txt").stat() {
/// Ok(stat) => stat,
/// Err(e) => panic!("couldn't read foo.txt: {}", e),
/// };
///
/// println!("byte size: {}", info.size);
/// # }
/// ```
#[deriving(Hash)]
pub struct FileStat {
/// The size of the file, in bytes
pub size: u64,
/// The kind of file this path points to (directory, file, pipe, etc.)
pub kind: FileType,
/// The file permissions currently on the file
pub perm: FilePermission,
// FIXME(#10301): These time fields are pretty useless without an actual
// time representation, what are the milliseconds relative
// to?
/// The time that the file was created at, in platform-dependent
/// milliseconds
pub created: u64,
/// The time that this file was last modified, in platform-dependent
/// milliseconds
pub modified: u64,
/// The time that this file was last accessed, in platform-dependent
/// milliseconds
pub accessed: u64,
/// Information returned by stat() which is not guaranteed to be
/// platform-independent. This information may be useful on some platforms,
/// but it may have different meanings or no meaning at all on other
/// platforms.
///
/// Usage of this field is discouraged, but if access is desired then the
/// fields are located here.
#[unstable]
pub unstable: UnstableFileStat,
}
impl Copy for FileStat {}
/// This structure represents all of the possible information which can be
/// returned from a `stat` syscall which is not contained in the `FileStat`
/// structure. This information is not necessarily platform independent, and may
/// have different meanings or no meaning at all on some platforms.
#[unstable]
#[deriving(Hash)]
pub struct UnstableFileStat {
/// The ID of the device containing the file.
pub device: u64,
/// The file serial number.
pub inode: u64,
/// The device ID.
pub rdev: u64,
/// The number of hard links to this file.
pub nlink: u64,
/// The user ID of the file.
pub uid: u64,
/// The group ID of the file.
pub gid: u64,
/// The optimal block size for I/O.
pub blksize: u64,
/// The blocks allocated for this file.
pub blocks: u64,
/// User-defined flags for the file.
pub flags: u64,
/// The file generation number.
pub gen: u64,
}
impl Copy for UnstableFileStat {}
bitflags! {
#[doc = "A set of permissions for a file or directory is represented"]
#[doc = "by a set of flags which are or'd together."]
flags FilePermission: u32 {
const USER_READ = 0o400,
const USER_WRITE = 0o200,
const USER_EXECUTE = 0o100,
const GROUP_READ = 0o040,
const GROUP_WRITE = 0o020,
const GROUP_EXECUTE = 0o010,
const OTHER_READ = 0o004,
const OTHER_WRITE = 0o002,
const OTHER_EXECUTE = 0o001,
const USER_RWX = USER_READ.bits | USER_WRITE.bits | USER_EXECUTE.bits,
const GROUP_RWX = GROUP_READ.bits | GROUP_WRITE.bits | GROUP_EXECUTE.bits,
const OTHER_RWX = OTHER_READ.bits | OTHER_WRITE.bits | OTHER_EXECUTE.bits,
#[doc = "Permissions for user owned files, equivalent to 0644 on"]
#[doc = "unix-like systems."]
const USER_FILE = USER_READ.bits | USER_WRITE.bits | GROUP_READ.bits | OTHER_READ.bits,
#[doc = "Permissions for user owned directories, equivalent to 0755 on"]
#[doc = "unix-like systems."]
const USER_DIR = USER_RWX.bits | GROUP_READ.bits | GROUP_EXECUTE.bits |
OTHER_READ.bits | OTHER_EXECUTE.bits,
#[doc = "Permissions for user owned executables, equivalent to 0755"]
#[doc = "on unix-like systems."]
const USER_EXEC = USER_DIR.bits,
#[doc = "All possible permissions enabled."]
const ALL_PERMISSIONS = USER_RWX.bits | GROUP_RWX.bits | OTHER_RWX.bits,
// Deprecated names
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_READ instead"]
const UserRead = USER_READ.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_WRITE instead"]
const UserWrite = USER_WRITE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_EXECUTE instead"]
const UserExecute = USER_EXECUTE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use GROUP_READ instead"]
const GroupRead = GROUP_READ.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use GROUP_WRITE instead"]
const GroupWrite = GROUP_WRITE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use GROUP_EXECUTE instead"]
const GroupExecute = GROUP_EXECUTE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use OTHER_READ instead"]
const OtherRead = OTHER_READ.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use OTHER_WRITE instead"]
const OtherWrite = OTHER_WRITE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use OTHER_EXECUTE instead"]
const OtherExecute = OTHER_EXECUTE.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_RWX instead"]
const UserRWX = USER_RWX.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use GROUP_RWX instead"]
const GroupRWX = GROUP_RWX.bits,
#[allow(non_upper_case_globals)]
#[deprecated = "use OTHER_RWX instead"]
const OtherRWX = OTHER_RWX.bits,
#[doc = "Deprecated: use `USER_FILE` instead."]
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_FILE instead"]
const UserFile = USER_FILE.bits,
#[doc = "Deprecated: use `USER_DIR` instead."]
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_DIR instead"]
const UserDir = USER_DIR.bits,
#[doc = "Deprecated: use `USER_EXEC` instead."]
#[allow(non_upper_case_globals)]
#[deprecated = "use USER_EXEC instead"]
const UserExec = USER_EXEC.bits,
#[doc = "Deprecated: use `ALL_PERMISSIONS` instead"]
#[allow(non_upper_case_globals)]
#[deprecated = "use ALL_PERMISSIONS instead"]
const AllPermissions = ALL_PERMISSIONS.bits,
}
}
#[stable]
impl Default for FilePermission {
#[stable]
#[inline]
fn default() -> FilePermission { FilePermission::empty() }
}
impl fmt::Show for FilePermission {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:04o}", self.bits)
}
}
#[cfg(test)]
mod tests {
use self::BadReaderBehavior::*;
use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput};
use prelude::*;
use uint;
#[deriving(Clone, PartialEq, Show)]
enum BadReaderBehavior {
GoodBehavior(uint),
BadBehavior(uint)
}
struct BadReader<T> {
r: T,
behavior: Vec<BadReaderBehavior>,
}
impl<T: Reader> BadReader<T> {
fn new(r: T, behavior: Vec<BadReaderBehavior>) -> BadReader<T> {
BadReader { behavior: behavior, r: r }
}
}
impl<T: Reader> Reader for BadReader<T> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let BadReader { ref mut behavior, ref mut r } = *self;
loop {
if behavior.is_empty() {
// fall back on good
return r.read(buf);
}
match behavior.as_mut_slice()[0] {
GoodBehavior(0) => (),
GoodBehavior(ref mut x) => {
*x -= 1;
return r.read(buf);
}
BadBehavior(0) => (),
BadBehavior(ref mut x) => {
*x -= 1;
return Ok(0);
}
};
behavior.remove(0);
}
}
}
#[test]
fn test_read_at_least() {
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![GoodBehavior(uint::MAX)]);
let buf = &mut [0u8, ..5];
assert!(r.read_at_least(1, buf).unwrap() >= 1);
assert!(r.read_exact(5).unwrap().len() == 5); // read_exact uses read_at_least
assert!(r.read_at_least(0, buf).is_ok());
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(50), GoodBehavior(uint::MAX)]);
assert!(r.read_at_least(1, buf).unwrap() >= 1);
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(1), GoodBehavior(1),
BadBehavior(50), GoodBehavior(uint::MAX)]);
assert!(r.read_at_least(1, buf).unwrap() >= 1);
assert!(r.read_at_least(1, buf).unwrap() >= 1);
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(uint::MAX)]);
assert_eq!(r.read_at_least(1, buf).unwrap_err().kind, NoProgress);
let mut r = MemReader::new(b"hello, world!".to_vec());
assert_eq!(r.read_at_least(5, buf).unwrap(), 5);
assert_eq!(r.read_at_least(6, buf).unwrap_err().kind, InvalidInput);
}
#[test]
fn test_push_at_least() {
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![GoodBehavior(uint::MAX)]);
let mut buf = Vec::new();
assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
assert!(r.push_at_least(0, 5, &mut buf).is_ok());
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(50), GoodBehavior(uint::MAX)]);
assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(1), GoodBehavior(1),
BadBehavior(50), GoodBehavior(uint::MAX)]);
assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
assert!(r.push_at_least(1, 5, &mut buf).unwrap() >= 1);
let mut r = BadReader::new(MemReader::new(b"hello, world!".to_vec()),
vec![BadBehavior(uint::MAX)]);
assert_eq!(r.push_at_least(1, 5, &mut buf).unwrap_err().kind, NoProgress);
let mut r = MemReader::new(b"hello, world!".to_vec());
assert_eq!(r.push_at_least(5, 1, &mut buf).unwrap_err().kind, InvalidInput);
}
#[test]
fn test_show() {
use super::*;
assert_eq!(format!("{}", USER_READ), "0400");
assert_eq!(format!("{}", USER_FILE), "0644");
assert_eq!(format!("{}", USER_EXEC), "0755");
assert_eq!(format!("{}", USER_RWX), "0700");
assert_eq!(format!("{}", GROUP_RWX), "0070");
assert_eq!(format!("{}", OTHER_RWX), "0007");
assert_eq!(format!("{}", ALL_PERMISSIONS), "0777");
assert_eq!(format!("{}", USER_READ | USER_WRITE | OTHER_WRITE), "0602");
}
fn _ensure_buffer_is_object_safe<T: Buffer>(x: &T) -> &Buffer {
x as &Buffer
}
}