diff --git a/src/libcore/rt/io/blocking/file.rs b/src/libcore/rt/io/blocking/file.rs new file mode 100644 index 00000000000..8daf8adf387 --- /dev/null +++ b/src/libcore/rt/io/blocking/file.rs @@ -0,0 +1,82 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Blocking posix-based file I/O + +use prelude::*; +use super::super::*; +use libc::{c_int, FILE}; + +#[allow(non_camel_case_types)] +pub type fd_t = c_int; + +// Make this a newtype so we can't do I/O on arbitrary integers +pub struct FileDesc(fd_t); + +impl FileDesc { + /// Create a `FileDesc` from an open C file descriptor. + /// + /// The `FileDesc` takes ownership of the file descriptor + /// and will close it upon destruction. + pub fn new(_fd: fd_t) -> FileDesc { fail!() } +} + +impl Reader for FileDesc { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for FileDesc { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for FileDesc { + fn close(&mut self) { fail!() } +} + +impl Seekable for FileDesc { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +pub struct CFile(*FILE); + +impl CFile { + /// Create a `CFile` from an open `FILE` pointer. + /// + /// The `CFile` takes ownership of the file descriptor + /// and will close it upon destruction. + pub fn new(_file: *FILE) -> CFile { fail!() } +} + +impl Reader for CFile { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for CFile { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for CFile { + fn close(&mut self) { fail!() } +} + +impl Seekable for CFile { + fn tell(&self) -> u64 { fail!() } + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} diff --git a/src/libcore/rt/io/comm_adapters.rs b/src/libcore/rt/io/comm_adapters.rs new file mode 100644 index 00000000000..1d6893b3ca6 --- /dev/null +++ b/src/libcore/rt/io/comm_adapters.rs @@ -0,0 +1,59 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::{Reader, Writer}; + +struct PortReader

; + +impl> PortReader

{ + pub fn new(_port: P) -> PortReader

{ fail!() } +} + +impl> Reader for PortReader

{ + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +struct ChanWriter; + +impl> ChanWriter { + pub fn new(_chan: C) -> ChanWriter { fail!() } +} + +impl> Writer for ChanWriter { + pub fn write(&mut self, _buf: &[u8]) { fail!() } + + pub fn flush(&mut self) { fail!() } +} + +struct ReaderPort; + +impl ReaderPort { + pub fn new(_reader: R) -> ReaderPort { fail!() } +} + +impl GenericPort<~[u8]> for ReaderPort { + fn recv(&self) -> ~[u8] { fail!() } + + fn try_recv(&self) -> Option<~[u8]> { fail!() } +} + +struct WriterChan; + +impl WriterChan { + pub fn new(_writer: W) -> WriterChan { fail!() } +} + +impl GenericChan<~[u8]> for WriterChan { + fn send(&self, _x: ~[u8]) { fail!() } +} + diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs index b7f3ed280a8..0fa357f0ac9 100644 --- a/src/libcore/rt/io/file.rs +++ b/src/libcore/rt/io/file.rs @@ -9,35 +9,79 @@ // except according to those terms. use prelude::*; -use super::Stream; +use super::misc::PathLike; +use super::{Reader, Writer, Seekable, Closeable}; +use super::{IoError, SeekStyle}; + +/// Open a file with the default FileMode and FileAccess +/// # TODO are there sane defaults here? +pub fn open_file(_path: &P) -> FileStream { fail!() } + +/// # TODO +/// * Ugh, this is ridiculous. What is the best way to represent these options? +enum FileMode { + /// Opens an existing file. IoError if file does not exist. + Open, + /// Creates a file. IoError if file exists. + Create, + /// Opens an existing file or creates a new one. + OpenOrCreate, + /// Opens an existing file or creates a new one, positioned at EOF. + Append, + /// Opens an existing file, truncating it to 0 bytes. + Truncate, + /// Opens an existing file or creates a new one, truncating it to 0 bytes. + CreateOrTruncate, +} + +enum FileAccess { + Read, + Write, + ReadWrite +} pub struct FileStream; -pub impl FileStream { - fn new(_path: Path) -> FileStream { +impl FileStream { + pub fn open(_path: &P, + _mode: FileMode, + _access: FileAccess + ) -> Result { fail!() } } -impl Stream for FileStream { - fn read(&mut self, _buf: &mut [u8]) -> uint { +impl Reader for FileStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } fn eof(&mut self) -> bool { fail!() } +} - fn write(&mut self, _v: &const [u8]) { - fail!() - } +impl Writer for FileStream { + fn write(&mut self, _v: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Seekable for FileStream { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Closeable for FileStream { + fn close(&mut self) { fail!() } } #[test] #[ignore] fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() { let message = "it's alright. have a good time"; - let filename = Path("test.txt"); - let mut outstream = FileStream::new(filename); + let filename = &Path("test.txt"); + let mut outstream = FileStream::open(filename, Create, Read).unwrap(); outstream.write(message.to_bytes()); } diff --git a/src/libcore/rt/io/flate.rs b/src/libcore/rt/io/flate.rs new file mode 100644 index 00000000000..24537bef329 --- /dev/null +++ b/src/libcore/rt/io/flate.rs @@ -0,0 +1,121 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Some various other I/O types + +// NOTE: These ultimately belong somewhere else + +use prelude::*; +use super::*; + +/// A Writer decorator that compresses using the 'deflate' scheme +pub struct DeflateWriter { + inner_writer: W +} + +impl DeflateWriter { + pub fn new(inner_writer: W) -> DeflateWriter { + DeflateWriter { + inner_writer: inner_writer + } + } +} + +impl Writer for DeflateWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Decorator for DeflateWriter { + fn inner(self) -> W { + match self { + DeflateWriter { inner_writer: w } => w + } + } + + fn inner_ref<'a>(&'a self) -> &'a W { + match *self { + DeflateWriter { inner_writer: ref w } => w + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { + match *self { + DeflateWriter { inner_writer: ref mut w } => w + } + } +} + +/// A Reader decorator that decompresses using the 'deflate' scheme +pub struct InflateReader { + inner_reader: R +} + +impl InflateReader { + pub fn new(inner_reader: R) -> InflateReader { + InflateReader { + inner_reader: inner_reader + } + } +} + +impl Reader for InflateReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Decorator for InflateReader { + fn inner(self) -> R { + match self { + InflateReader { inner_reader: r } => r + } + } + + fn inner_ref<'a>(&'a self) -> &'a R { + match *self { + InflateReader { inner_reader: ref r } => r + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { + match *self { + InflateReader { inner_reader: ref mut r } => r + } + } +} + +#[cfg(test)] +mod test { + use prelude::*; + use super::*; + use super::super::mem::*; + use super::super::Decorator; + + #[test] + #[ignore] + fn smoke_test() { + let mem_writer = MemWriter::new(); + let mut deflate_writer = DeflateWriter::new(mem_writer); + let in_msg = "test"; + let in_bytes = in_msg.to_bytes(); + deflate_writer.write(in_bytes); + deflate_writer.flush(); + let buf = deflate_writer.inner().inner(); + let mem_reader = MemReader::new(buf); + let mut inflate_reader = InflateReader::new(mem_reader); + let mut out_bytes = [0, .. 100]; + let bytes_read = inflate_reader.read(out_bytes).get(); + assert!(bytes_read == in_bytes.len()); + let out_msg = str::from_bytes(out_bytes); + assert!(in_msg == out_msg); + } +} \ No newline at end of file diff --git a/src/libcore/rt/io/mem.rs b/src/libcore/rt/io/mem.rs new file mode 100644 index 00000000000..04790c57913 --- /dev/null +++ b/src/libcore/rt/io/mem.rs @@ -0,0 +1,166 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Readers and Writers for in-memory buffers +//! +//! # TODO +//! +//! * Should probably have something like this for strings. +//! * Should they implement Closable? Would take extra state. + +use prelude::*; +use super::*; + + +/// Writes to an owned, growable byte vector +pub struct MemWriter { + buf: ~[u8] +} + +impl MemWriter { + pub fn new() -> MemWriter { MemWriter { buf: ~[] } } +} + +impl Writer for MemWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { /* no-op */ } +} + +impl Seekable for MemWriter { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Decorator<~[u8]> for MemWriter { + + fn inner(self) -> ~[u8] { + match self { + MemWriter { buf: buf } => buf + } + } + + fn inner_ref<'a>(&'a self) -> &'a ~[u8] { + match *self { + MemWriter { buf: ref buf } => buf + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { + match *self { + MemWriter { buf: ref mut buf } => buf + } + } +} + +/// Reads from an owned byte vector +pub struct MemReader { + buf: ~[u8], + pos: uint +} + +impl MemReader { + pub fn new(buf: ~[u8]) -> MemReader { + MemReader { + buf: buf, + pos: 0 + } + } +} + +impl Reader for MemReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Seekable for MemReader { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + +impl Decorator<~[u8]> for MemReader { + + fn inner(self) -> ~[u8] { + match self { + MemReader { buf: buf, _ } => buf + } + } + + fn inner_ref<'a>(&'a self) -> &'a ~[u8] { + match *self { + MemReader { buf: ref buf, _ } => buf + } + } + + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { + match *self { + MemReader { buf: ref mut buf, _ } => buf + } + } +} + + +/// Writes to a fixed-size byte slice +struct BufWriter<'self> { + buf: &'self mut [u8], + pos: uint +} + +impl<'self> BufWriter<'self> { + pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> { + BufWriter { + buf: buf, + pos: 0 + } + } +} + +impl<'self> Writer for BufWriter<'self> { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl<'self> Seekable for BufWriter<'self> { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} + + +/// Reads from a fixed-size byte slice +struct BufReader<'self> { + buf: &'self [u8], + pos: uint +} + +impl<'self> BufReader<'self> { + pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> { + BufReader { + buf: buf, + pos: 0 + } + } +} + +impl<'self> Reader for BufReader<'self> { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl<'self> Seekable for BufReader<'self> { + fn tell(&self) -> u64 { fail!() } + + fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() } +} \ No newline at end of file diff --git a/src/libcore/rt/io/misc.rs b/src/libcore/rt/io/misc.rs new file mode 100644 index 00000000000..7bace5d6df2 --- /dev/null +++ b/src/libcore/rt/io/misc.rs @@ -0,0 +1,42 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use path::*; + +pub trait PathLike { + fn path_as_str(&self, f: &fn(&str) -> T) -> T; +} + +impl<'self> PathLike for &'self str { + fn path_as_str(&self, f: &fn(&str) -> T) -> T { + f(*self) + } +} + +impl PathLike for Path { + fn path_as_str(&self, f: &fn(&str) -> T) -> T { + let s = self.to_str(); + f(s) + } +} + +#[cfg(test)] +mod test { + use path::*; + use super::PathLike; + + #[test] + fn path_like_smoke_test() { + let expected = "/home"; + let path = Path(expected); + path.path_as_str(|p| assert!(p == expected)); + path.path_as_str(|p| assert!(p == expected)); + } +} diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs index 1634e7443b4..e711c2ff66e 100644 --- a/src/libcore/rt/io/mod.rs +++ b/src/libcore/rt/io/mod.rs @@ -8,35 +8,276 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/*! Synchronous I/O + +This module defines the Rust interface for synchronous I/O. +It supports file access, + +This will likely live in core::io, not core::rt::io. + +# Examples + +Some examples of obvious things you might want to do + +* Read lines from stdin + + for stdin().each_line |line| { + println(line) + } + +* Read a complete file to a string, (converting newlines?) + + let contents = open("message.txt").read_to_str(); // read_to_str?? + +* Write a line to a file + + let file = FileStream::open("message.txt", Create, Write); + file.write_line("hello, file!"); + +* Iterate over the lines of a file + +* Pull the lines of a file into a vector of strings + +* Connect based on URL? Requires thinking about where the URL type lives + and how to make protocol handlers extensible, e.g. the "tcp" protocol + yields a `TcpStream`. + + connect("tcp://localhost:8080").write_line("HTTP 1.0 GET /"); + +# Terms + +* reader +* writer +* stream +* Blocking vs. non-blocking +* synchrony and asynchrony + +I tend to call this implementation non-blocking, because performing I/O +doesn't block the progress of other tasks. Is that how we want to present +it, 'synchronous but non-blocking'? + +# Error Handling + +# Resource management + +* `close` vs. RAII + +# Paths and URLs + +# std + +Some I/O things don't belong in core + + - url + - net - `fn connect` + - http + - flate + +# TODO + +* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose. + Overloading would be nice. +* Add overloading for Path and &str and Url &str +* stdin/err/out +* print, println, etc. +* fsync +* relationship with filesystem querying, Directory, File types etc. +* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic? +* Trait for things that are both readers and writers, Stream? +* How to handle newline conversion +* String conversion +* File vs. FileStream? File is shorter but could also be used for getting file info + - maybe File is for general file querying and *also* has a static `open` method +* open vs. connect for generic stream opening +* Do we need `close` at all? dtors might be good enough +* How does I/O relate to the Iterator trait? +* std::base64 filters + +*/ + +use prelude::*; + +// 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::file::open_file; +pub use self::file::FileStream; +pub use self::net::Listener; +pub use self::net::ip::IpAddr; +pub use self::net::tcp::TcpListener; +pub use self::net::tcp::TcpStream; +pub use self::net::udp::UdpStream; + +// Some extension traits that all Readers and Writers get. +pub use self::util::ReaderUtil; +pub use self::util::ReaderByteConversions; +pub use self::util::WriterByteConversions; + +/// Synchronous, non-blocking file I/O. pub mod file; -// FIXME #5370 Strongly want this to be StreamError(&mut Stream) -pub struct StreamError; +/// Synchronous, non-blocking network I/O. +#[path = "net/mod.rs"] +pub mod net; -// XXX: Can't put doc comments on macros -// Raised by `Stream` instances on error. Returning `true` from the handler -// indicates that the `Stream` should continue, `false` that it should fail. -condition! { - stream_error: super::StreamError -> bool; +/// Readers and Writers for memory buffers and strings. +#[cfg(not(stage0))] // XXX Using unsnapshotted features +pub mod mem; + +/// Non-blocking access to stdin, stdout, stderr +pub mod stdio; + +/// Basic stream compression. XXX: Belongs with other flate code +#[cfg(not(stage0))] // XXX Using unsnapshotted features +pub mod flate; + +/// Interop between byte streams and pipes. Not sure where it belongs +#[cfg(not(stage0))] // XXX " +pub mod comm_adapters; + +/// Extension traits +mod util; + +/// Non-I/O things needed by the I/O module +mod misc; + +/// Thread-blocking implementations +pub mod blocking { + /// Posix file I/O + pub mod file; + /// # TODO - implement this + pub mod stdio { } + /// Sockets + /// # TODO - implement this + pub mod net { + pub mod tcp { } + pub mod udp { } + #[cfg(unix)] + pub mod unix { } + } } -pub trait Stream { - /// Read bytes, up to the length of `buf` and place them in `buf`, - /// returning the number of bytes read or an `IoError`. Reads - /// 0 bytes on EOF. + +/// The type passed to I/O condition handlers to indicate error +/// +/// # TODO +/// +/// Is something like this sufficient? It's kind of archaic +pub struct IoError { + kind: IoErrorKind, + desc: &'static str, + detail: Option<~str> +} + +pub enum IoErrorKind { + FileNotFound, + FilePermission, + ConnectionFailed, + Closed, + OtherIoError +} + +// XXX: Can't put doc comments on macros +// Raised by `I/O` operations on error. +condition! { + io_error: super::IoError -> (); +} + +pub trait Reader { + /// Read bytes, up to the length of `buf` and place them in `buf`. + /// Returns the number of bytes read, or `None` on EOF. /// /// # Failure /// - /// Raises the `reader_error` condition on error - fn read(&mut self, buf: &mut [u8]) -> uint; + /// Raises the `io_error` condition on error, then returns `None`. + /// + /// # TODO + /// + /// This doesn't take a `len` argument like the old `read`. + /// Will people often need to slice their vectors to call this + /// and will that be annoying? + fn read(&mut self, buf: &mut [u8]) -> Option; - /// Return whether the Reader has reached the end of the stream + /// Return whether the Reader has reached the end of the stream. + /// + /// # Example + /// + /// let reader = FileStream::new() + /// while !reader.eof() { + /// println(reader.read_line()); + /// } + /// + /// # TODO + /// + /// What does this return if the Reader is in an error state? fn eof(&mut self) -> bool; +} +pub trait Writer { /// Write the given buffer /// /// # Failure /// - /// Raises the `writer_error` condition on error - fn write(&mut self, v: &const [u8]); + /// Raises the `io_error` condition on error + fn write(&mut self, buf: &[u8]); + + /// Flush output + fn flush(&mut self); +} + +/// I/O types that may be closed +/// +/// Any further operations performed on a closed resource will raise +/// on `io_error` +pub trait Closeable { + /// Close the I/O resource + fn close(&mut self); +} + +pub trait Stream: Reader + Writer + Closeable { } + +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, +} + +/// # TODO +/// * Are `u64` and `i64` the right choices? +pub trait Seekable { + fn tell(&self) -> u64; + fn seek(&mut self, pos: i64, style: SeekStyle); +} + +/// Common trait for decorator types. +/// +/// Provides accessors to get the inner, 'decorated' values. The I/O library +/// uses decorators to add functionality like compression and encryption to I/O +/// streams. +/// +/// # TODO +/// +/// Is this worth having a trait for? May be overkill +pub trait Decorator { + /// Destroy the decorator and extract the decorated value + /// + /// # TODO + /// + /// Because this takes `self' one could never 'undecorate' a Reader/Writer + /// that has been boxed. Is that ok? This feature is mostly useful for + /// extracting the buffer from MemWriter + fn inner(self) -> T; + + /// Take an immutable reference to the decorated value + fn inner_ref<'a>(&'a self) -> &'a T; + + /// Take a mutable reference to the decorated value + fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T; } diff --git a/src/libcore/rt/io/net/http.rs b/src/libcore/rt/io/net/http.rs new file mode 100644 index 00000000000..40f0b315e05 --- /dev/null +++ b/src/libcore/rt/io/net/http.rs @@ -0,0 +1,29 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Simple HTTP client and server + +// XXX This should not be in core + +struct HttpServer; + +#[cfg(test)] +mod test { + use unstable::run_in_bare_thread; + + #[test] #[ignore] + fn smoke_test() { + do run_in_bare_thread { + } + + do run_in_bare_thread { + } + } +} diff --git a/src/libcore/rt/io/net/ip.rs b/src/libcore/rt/io/net/ip.rs new file mode 100644 index 00000000000..d9b7f4e6e40 --- /dev/null +++ b/src/libcore/rt/io/net/ip.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub enum IpAddr { + Ipv4(u8, u8, u8, u8, u16), + Ipv6 +} + diff --git a/src/libcore/rt/io/net/mod.rs b/src/libcore/rt/io/net/mod.rs new file mode 100644 index 00000000000..130ff6b38fa --- /dev/null +++ b/src/libcore/rt/io/net/mod.rs @@ -0,0 +1,31 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; + +pub mod tcp; +pub mod udp; +pub mod ip; +#[cfg(unix)] +pub mod unix; +pub mod http; + +/// A listener is a value that listens for connections +pub trait Listener { + /// Wait for and accept an incoming connection + /// + /// Returns `None` on timeout. + /// + /// # Failure + /// + /// Raises `io_error` condition. If the condition is handled, + /// then `accept` returns `None`. + fn accept(&mut self) -> Option; +} diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs new file mode 100644 index 00000000000..ddd75cd8415 --- /dev/null +++ b/src/libcore/rt/io/net/tcp.rs @@ -0,0 +1,50 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::ip::IpAddr; + +pub struct TcpStream; + +impl TcpStream { + pub fn connect(_addr: IpAddr) -> Result { + fail!() + } +} + +impl Reader for TcpStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for TcpStream { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for TcpStream { + fn close(&mut self) { fail!() } +} + +pub struct TcpListener; + +impl TcpListener { + pub fn new(_addr: IpAddr) -> TcpListener { + fail!() + } +} + +impl Listener for TcpListener { + fn accept(&mut self) -> Option { fail!() } +} diff --git a/src/libcore/rt/io/net/udp.rs b/src/libcore/rt/io/net/udp.rs new file mode 100644 index 00000000000..a0f7aa81989 --- /dev/null +++ b/src/libcore/rt/io/net/udp.rs @@ -0,0 +1,51 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::ip::IpAddr; + +pub struct UdpStream; + +impl UdpStream { + pub fn connect(_addr: IpAddr) -> Result { + fail!() + } +} + +impl Reader for UdpStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for UdpStream { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for UdpStream { + fn close(&mut self) { fail!() } +} + +pub struct UdpListener; + +impl UdpListener { + pub fn new(_addr: IpAddr) -> UdpListener { + fail!() + } +} + +impl Listener for UdpListener { + fn accept(&mut self) -> Option { fail!() } +} + diff --git a/src/libcore/rt/io/net/unix.rs b/src/libcore/rt/io/net/unix.rs new file mode 100644 index 00000000000..fde87deef33 --- /dev/null +++ b/src/libcore/rt/io/net/unix.rs @@ -0,0 +1,51 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::*; +use super::super::*; +use super::super::misc::PathLike; + +pub struct UnixStream; + +impl UnixStream { + pub fn connect(_path: &P) -> Result { + fail!() + } +} + +impl Reader for UnixStream { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Writer for UnixStream { + fn write(&mut self, _v: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for UnixStream { + fn close(&mut self) { fail!() } +} + +pub struct UnixListener; + +impl UnixListener { + pub fn new(_path: &P) -> UnixListener { + fail!() + } +} + +impl Listener for UnixListener { + fn accept(&mut self) -> Option { fail!() } +} + diff --git a/src/libcore/rt/io/stdio.rs b/src/libcore/rt/io/stdio.rs new file mode 100644 index 00000000000..3a742266f81 --- /dev/null +++ b/src/libcore/rt/io/stdio.rs @@ -0,0 +1,60 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::*; +use super::{Reader, Writer, Closeable}; + +pub fn stdin() -> StdReader { fail!() } + +pub fn stdout() -> StdWriter { fail!() } + +pub fn stderr() -> StdReader { fail!() } + +pub fn print(s: &str) { fail!() } + +pub fn println(s: &str) { fail!() } + +pub enum StdStream { + StdIn, + StdOut, + StdErr +} + +pub struct StdReader; + +impl StdReader { + pub fn new(_stream: StdStream) -> StdReader { fail!() } +} + +impl Reader for StdReader { + fn read(&mut self, _buf: &mut [u8]) -> Option { fail!() } + + fn eof(&mut self) -> bool { fail!() } +} + +impl Closeable for StdReader { + fn close(&mut self) { fail!() } +} + +pub struct StdWriter; + +impl StdWriter { + pub fn new(_stream: StdStream) -> StdWriter { fail!() } +} + +impl Writer for StdWriter { + fn write(&mut self, _buf: &[u8]) { fail!() } + + fn flush(&mut self) { fail!() } +} + +impl Closeable for StdWriter { + fn close(&mut self) { fail!() } +} diff --git a/src/libcore/rt/io/util.rs b/src/libcore/rt/io/util.rs new file mode 100644 index 00000000000..d695815adce --- /dev/null +++ b/src/libcore/rt/io/util.rs @@ -0,0 +1,469 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Utility mixins that apply to all Readers and Writers + +// TODO: Not sure how this should be structured +// TODO: Iteration should probably be considered seperately + +pub trait ReaderUtil { + + /// Reads `len` bytes and gives you back a new vector + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns an empty + /// vector if the condition is handled. + fn read_bytes(&mut self, len: uint) -> ~[u8]; + + /// Reads all remaining bytes from the stream. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns an empty + /// vector if the condition is handled. + fn read_to_end(&mut self) -> ~[u8]; + +} + +pub trait ReaderByteConversions { + /// Reads `n` little-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` little-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads `n` big-endian unsigned integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_uint_n(&mut self, nbytes: uint) -> u64; + + /// Reads `n` big-endian signed integer bytes. + /// + /// `n` must be between 1 and 8, inclusive. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_int_n(&mut self, nbytes: uint) -> i64; + + /// Reads a little-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_uint(&mut self) -> uint; + + /// Reads a little-endian integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_int(&mut self) -> int; + + /// Reads a big-endian unsigned integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_uint(&mut self) -> uint; + + /// Reads a big-endian integer. + /// + /// The number of bytes returned is system-dependant. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_int(&mut self) -> int; + + /// Reads a big-endian `u64`. + /// + /// `u64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u64(&mut self) -> u64; + + /// Reads a big-endian `u32`. + /// + /// `u32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u32(&mut self) -> u32; + + /// Reads a big-endian `u16`. + /// + /// `u16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_u16(&mut self) -> u16; + + /// Reads a big-endian `i64`. + /// + /// `i64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i64(&mut self) -> i64; + + /// Reads a big-endian `i32`. + /// + /// `i32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i32(&mut self) -> i32; + + /// Reads a big-endian `i16`. + /// + /// `i16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_i16(&mut self) -> i16; + + /// Reads a big-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_f64(&mut self) -> f64; + + /// Reads a big-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_be_f32(&mut self) -> f32; + + /// Reads a little-endian `u64`. + /// + /// `u64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u64(&mut self) -> u64; + + /// Reads a little-endian `u32`. + /// + /// `u32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u32(&mut self) -> u32; + + /// Reads a little-endian `u16`. + /// + /// `u16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_u16(&mut self) -> u16; + + /// Reads a little-endian `i64`. + /// + /// `i64`s are 8 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i64(&mut self) -> i64; + + /// Reads a little-endian `i32`. + /// + /// `i32`s are 4 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i32(&mut self) -> i32; + + /// Reads a little-endian `i16`. + /// + /// `i16`s are 2 bytes long. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_i16(&mut self) -> i16; + + /// Reads a little-endian `f64`. + /// + /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_f64(&mut self) -> f64; + + /// Reads a little-endian `f32`. + /// + /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_le_f32(&mut self) -> f32; + + /// Read a u8. + /// + /// `u8`s are 1 byte. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_u8(&mut self) -> u8; + + /// Read an i8. + /// + /// `i8`s are 1 byte. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. Returns `0` if + /// the condition is handled. + fn read_i8(&mut self) -> i8; + +} + +pub trait WriterByteConversions { + /// Write the result of passing n through `int::to_str_bytes`. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_int(&mut self, n: int); + + /// Write the result of passing n through `uint::to_str_bytes`. + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_uint(&mut self, n: uint); + + /// Write a little-endian uint (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_uint(&mut self, n: uint); + + /// Write a little-endian int (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_int(&mut self, n: int); + + /// Write a big-endian uint (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_uint(&mut self, n: uint); + + /// Write a big-endian int (number of bytes depends on system). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_int(&mut self, n: int); + + /// Write a big-endian u64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u64(&mut self, n: u64); + + /// Write a big-endian u32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u32(&mut self, n: u32); + + /// Write a big-endian u16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_u16(&mut self, n: u16); + + /// Write a big-endian i64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i64(&mut self, n: i64); + + /// Write a big-endian i32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i32(&mut self, n: i32); + + /// Write a big-endian i16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_i16(&mut self, n: i16); + + /// Write a big-endian IEEE754 double-precision floating-point (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_f64(&mut self, f: f64); + + /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_be_f32(&mut self, f: f32); + + /// Write a little-endian u64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u64(&mut self, n: u64); + + /// Write a little-endian u32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u32(&mut self, n: u32); + + /// Write a little-endian u16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_u16(&mut self, n: u16); + + /// Write a little-endian i64 (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i64(&mut self, n: i64); + + /// Write a little-endian i32 (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i32(&mut self, n: i32); + + /// Write a little-endian i16 (2 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_i16(&mut self, n: i16); + + /// Write a little-endian IEEE754 double-precision floating-point + /// (8 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_f64(&mut self, f: f64); + + /// Write a litten-endian IEEE754 single-precision floating-point + /// (4 bytes). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_le_f32(&mut self, f: f32); + + /// Write a u8 (1 byte). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_u8(&mut self, n: u8); + + /// Write a i8 (1 byte). + /// + /// # Failure + /// + /// Raises the `io_error` condition on error. + fn write_i8(&mut self, n: i8); +} diff --git a/src/libcore/rt/rtio.rs b/src/libcore/rt/rtio.rs index 6a7c3970c00..66eb79ba6ae 100644 --- a/src/libcore/rt/rtio.rs +++ b/src/libcore/rt/rtio.rs @@ -11,6 +11,8 @@ use option::*; use result::*; +use super::io::net::ip::IpAddr; + // XXX: ~object doesn't work currently so these are some placeholder // types to use instead pub type EventLoopObject = super::uvio::UvEventLoop; @@ -43,8 +45,3 @@ pub trait Stream { fn read(&mut self, buf: &mut [u8]) -> Result; fn write(&mut self, buf: &[u8]) -> Result<(), ()>; } - -pub enum IpAddr { - Ipv4(u8, u8, u8, u8, u16), - Ipv6 -} diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs index 4b9ff4504dd..0dc1a4d86cb 100644 --- a/src/libcore/rt/uv/net.rs +++ b/src/libcore/rt/uv/net.rs @@ -17,7 +17,7 @@ use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCa loop_from_watcher, status_to_maybe_uv_error, install_watcher_data, get_watcher_data, drop_watcher_data, vec_to_uv_buf, vec_from_uv_buf}; -use super::super::rtio::{IpAddr, Ipv4, Ipv6}; +use super::super::io::net::ip::{IpAddr, Ipv4, Ipv6}; #[cfg(test)] use unstable::run_in_bare_thread; diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs index fe7b0a71dbf..b069c67a5f7 100644 --- a/src/libcore/rt/uvio.rs +++ b/src/libcore/rt/uvio.rs @@ -11,6 +11,7 @@ use option::*; use result::*; +use super::io::net::ip::{IpAddr, Ipv4}; use super::uv::*; use super::rtio::*; use ops::Drop;