Migrated to new std::io.

This commit is contained in:
Aaron Weiss 2015-03-02 17:12:16 -05:00
parent 9d695a1ee5
commit 8bc8b946f7
8 changed files with 221 additions and 217 deletions

View file

@ -2,72 +2,76 @@
#![stable]
#[cfg(feature = "ssl")] use std::borrow::ToOwned;
#[cfg(feature = "ssl")] use std::error::Error;
use std::old_io::{BufferedReader, BufferedWriter, IoResult, TcpStream};
#[cfg(any(feature = "encode", feature = "ssl"))] use std::old_io::{IoError, IoErrorKind};
use std::io::prelude::*;
use std::io::{BufReader, BufWriter, Result};
use std::io::Error as IoError;
use std::io::ErrorKind;
use std::net::TcpStream;
#[cfg(feature = "ssl")] use std::result::Result as StdResult;
use std::sync::{Mutex, MutexGuard};
#[cfg(feature = "encode")] use encoding::{DecoderTrap, EncoderTrap, Encoding};
#[cfg(feature = "encode")] use encoding::label::encoding_from_whatwg_label;
use client::data::kinds::{IrcReader, IrcWriter};
use client::data::kinds::{IrcRead, IrcWrite};
use client::data::message::ToMessage;
#[cfg(feature = "ssl")] use openssl::ssl::{SslContext, SslMethod, SslStream};
#[cfg(feature = "ssl")] use openssl::ssl::error::SslError;
/// A thread-safe connection.
#[stable]
pub struct Connection<T: IrcReader, U: IrcWriter> {
pub struct Connection<T: IrcRead, U: IrcWrite> {
reader: Mutex<T>,
writer: Mutex<U>,
}
/// A Connection over a buffered NetStream.
#[stable]
pub type NetConnection = Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
pub type NetConnection = Connection<BufReader<NetStream>, BufWriter<NetStream>>;
/// An internal type
type NetReaderWriterPair = (BufferedReader<NetStream>, BufferedWriter<NetStream>);
type NetReadWritePair = (BufReader<NetStream>, BufWriter<NetStream>);
#[stable]
impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
impl Connection<BufReader<NetStream>, BufWriter<NetStream>> {
/// Creates a thread-safe TCP connection to the specified server.
#[stable]
pub fn connect(host: &str, port: u16) -> IoResult<NetConnection> {
pub fn connect(host: &str, port: u16) -> Result<NetConnection> {
let (reader, writer) = try!(Connection::connect_internal(host, port));
Ok(Connection::new(reader, writer))
}
/// connects to the specified server and returns a reader-writer pair.
fn connect_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
fn connect_internal(host: &str, port: u16) -> Result<NetReadWritePair> {
let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
Ok((BufferedReader::new(NetStream::UnsecuredTcpStream(socket.clone())),
BufferedWriter::new(NetStream::UnsecuredTcpStream(socket))))
Ok((BufReader::new(NetStream::UnsecuredTcpStream(try!(socket.try_clone()))),
BufWriter::new(NetStream::UnsecuredTcpStream(socket))))
}
/// Creates a thread-safe TCP connection to the specified server over SSL.
/// If the library is compiled without SSL support, this method panics.
#[stable]
pub fn connect_ssl(host: &str, port: u16) -> IoResult<NetConnection> {
pub fn connect_ssl(host: &str, port: u16) -> Result<NetConnection> {
let (reader, writer) = try!(Connection::connect_ssl_internal(host, port));
Ok(Connection::new(reader, writer))
}
/// Connects over SSL to the specified server and returns a reader-writer pair.
#[cfg(feature = "ssl")]
fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
fn connect_ssl_internal(host: &str, port: u16) -> Result<NetReadWritePair> {
let socket = try!(TcpStream::connect(&format!("{}:{}", host, port)[..]));
let ssl = try!(ssl_to_io(SslContext::new(SslMethod::Tlsv1)));
let ssl_socket = try!(ssl_to_io(SslStream::new(&ssl, socket)));
Ok((BufferedReader::new(NetStream::SslTcpStream(ssl_socket.clone())),
BufferedWriter::new(NetStream::SslTcpStream(ssl_socket))))
Ok((BufReader::new(NetStream::SslTcpStream(try!(ssl_socket.try_clone()))),
BufWriter::new(NetStream::SslTcpStream(ssl_socket))))
}
/// Panics because SSL support is not compiled in.
#[cfg(not(feature = "ssl"))]
fn connect_ssl_internal(host: &str, port: u16) -> IoResult<NetReaderWriterPair> {
fn connect_ssl_internal(host: &str, port: u16) -> Result<NetReadWritePair> {
panic!("Cannot connect to {}:{} over SSL without compiling with SSL support.", host, port)
}
/// Reconnects to the specified server, dropping the current connection.
#[stable]
pub fn reconnect(&self, host: &str, port: u16) -> IoResult<()> {
pub fn reconnect(&self, host: &str, port: u16) -> Result<()> {
let use_ssl = match self.reader.lock().unwrap().get_ref() {
&NetStream::UnsecuredTcpStream(_) => false,
#[cfg(feature = "ssl")]
@ -85,18 +89,12 @@ impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
/// Sets the keepalive for the network stream.
#[unstable = "Rust IO has not stabilized."]
pub fn set_keepalive(&self, delay_in_seconds: Option<usize>) -> IoResult<()> {
pub fn set_keepalive(&self, delay_in_seconds: Option<u32>) -> Result<()> {
self.mod_stream(|tcp| tcp.set_keepalive(delay_in_seconds))
}
/// Sets the timeout for the network stream.
#[unstable = "Rust IO has not stabilized."]
pub fn set_timeout(&self, timeout_ms: Option<u64>) {
self.mod_stream(|tcp| Ok(tcp.set_timeout(timeout_ms))).unwrap(); // this cannot fail.
}
/// Modifies the internal TcpStream using a function.
fn mod_stream<F>(&self, f: F) -> IoResult<()> where F: FnOnce(&mut TcpStream) -> IoResult<()> {
fn mod_stream<F>(&self, f: F) -> Result<()> where F: FnOnce(&mut TcpStream) -> Result<()> {
match self.reader.lock().unwrap().get_mut() {
&mut NetStream::UnsecuredTcpStream(ref mut tcp) => f(tcp),
#[cfg(feature = "ssl")]
@ -106,7 +104,7 @@ impl Connection<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
}
#[stable]
impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
impl<T: IrcRead, U: IrcWrite> Connection<T, U> {
/// Creates a new connection from an IrcReader and an IrcWriter.
#[stable]
pub fn new(reader: T, writer: U) -> Connection<T, U> {
@ -119,23 +117,19 @@ impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
/// Sends a Message over this connection.
#[stable]
#[cfg(feature = "encode")]
pub fn send<M: ToMessage>(&self, to_msg: M, encoding: &str) -> IoResult<()> {
pub fn send<M: ToMessage>(&self, to_msg: M, encoding: &str) -> Result<()> {
let encoding = match encoding_from_whatwg_label(encoding) {
Some(enc) => enc,
None => return Err(IoError {
kind: IoErrorKind::InvalidInput,
desc: "Failed to find decoder.",
detail: Some(format!("Invalid decoder: {}", encoding))
})
None => return Err(IoError::new(ErrorKind::InvalidInput, "Failed to find encoder.",
Some(format!("Invalid encoder: {}", encoding))))
};
let msg = to_msg.to_message();
let data = match encoding.encode(&msg.into_string(), EncoderTrap::Replace) {
Ok(data) => data,
Err(data) => return Err(IoError {
kind: IoErrorKind::InvalidInput,
desc: "Failed to decode message.",
detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
})
Err(data) => return Err(IoError::new(
ErrorKind::InvalidInput, "Failed to encode message.",
Some(format!("Failed to encode {} as {}.", data, encoding.name()))
))
};
let mut writer = self.writer.lock().unwrap();
try!(writer.write_all(&data));
@ -145,32 +139,28 @@ impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
/// Sends a message over this connection.
#[stable]
#[cfg(not(feature = "encode"))]
pub fn send<M: ToMessage>(&self, to_msg: M) -> IoResult<()> {
pub fn send<M: ToMessage>(&self, to_msg: M) -> Result<()> {
let mut writer = self.writer.lock().unwrap();
try!(writer.write_str(&to_msg.to_message().into_string()));
try!(writer.write_all(&to_msg.to_message().into_string().as_bytes()));
writer.flush()
}
/// Receives a single line from this connection.
#[stable]
#[cfg(feature = "encoding")]
pub fn recv(&self, encoding: &str) -> IoResult<String> {
pub fn recv(&self, encoding: &str) -> Result<String> {
let encoding = match encoding_from_whatwg_label(encoding) {
Some(enc) => enc,
None => return Err(IoError {
kind: IoErrorKind::InvalidInput,
desc: "Failed to find decoder.",
detail: Some(format!("Invalid decoder: {}", encoding))
})
None => return Err(IoError::new(ErrorKind::InvalidInput, "Failed to find decoder.",
Some(format!("Invalid decoder: {}", encoding))))
};
self.reader.lock().unwrap().read_until(b'\n').and_then(|line|
match encoding.decode(&line, DecoderTrap::Replace) {
let mut buf = Vec::new();
self.reader.lock().unwrap().read_until(b'\n', &mut buf).and_then(|_|
match encoding.decode(&buf, DecoderTrap::Replace) {
_ if buf.is_empty() => Err(IoError::new(ErrorKind::Other, "EOF", None)),
Ok(data) => Ok(data),
Err(data) => Err(IoError {
kind: IoErrorKind::InvalidInput,
desc: "Failed to decode message.",
detail: Some(format!("Failed to decode {} as {}.", data, encoding.name())),
})
Err(data) => Err(IoError::new(ErrorKind::InvalidInput, "Failed to decode message.",
Some(format!("Failed to decode {} as {}.", data, encoding.name()))))
}
)
}
@ -178,8 +168,14 @@ impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
/// Receives a single line from this connection.
#[stable]
#[cfg(not(feature = "encoding"))]
pub fn recv(&self) -> IoResult<String> {
self.reader.lock().unwrap().read_line()
pub fn recv(&self) -> Result<String> {
let mut ret = String::new();
try!(self.reader.lock().unwrap().read_line(&mut ret));
if ret.is_empty() {
Err(IoError::new(ErrorKind::Other, "EOF", None))
} else {
Ok(ret)
}
}
/// Acquires the Reader lock.
@ -195,16 +191,13 @@ impl<T: IrcReader, U: IrcWriter> Connection<T, U> {
}
}
/// Converts a Result<T, SslError> into an IoResult<T>.
/// Converts a Result<T, SslError> into an Result<T>.
#[cfg(feature = "ssl")]
fn ssl_to_io<T>(res: Result<T, SslError>) -> IoResult<T> {
fn ssl_to_io<T>(res: StdResult<T, SslError>) -> Result<T> {
match res {
Ok(x) => Ok(x),
Err(e) => Err(IoError {
kind: IoErrorKind::OtherIoError,
desc: "An SSL error occurred.",
detail: Some(e.description().to_owned()),
}),
Err(e) => Err(IoError::new(ErrorKind::Other, "An SSL error occurred.",
Some(e.description().to_owned()))),
}
}
@ -221,8 +214,8 @@ pub enum NetStream {
SslTcpStream(SslStream<TcpStream>),
}
impl Reader for NetStream {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
impl Read for NetStream {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
match self {
&mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.read(buf),
#[cfg(feature = "ssl")]
@ -231,12 +224,20 @@ impl Reader for NetStream {
}
}
impl Writer for NetStream {
fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
impl Write for NetStream {
fn write(&mut self, buf: &[u8]) -> Result<usize> {
match self {
&mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.write_all(buf),
&mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.write(buf),
#[cfg(feature = "ssl")]
&mut NetStream::SslTcpStream(ref mut stream) => stream.write_all(buf),
&mut NetStream::SslTcpStream(ref mut stream) => stream.write(buf),
}
}
fn flush(&mut self) -> Result<()> {
match self {
&mut NetStream::UnsecuredTcpStream(ref mut stream) => stream.flush(),
#[cfg(feature = "ssl")]
&mut NetStream::SslTcpStream(ref mut stream) => stream.flush(),
}
}
}
@ -244,20 +245,20 @@ impl Writer for NetStream {
#[cfg(test)]
mod test {
use super::Connection;
use std::old_io::{MemReader, MemWriter};
use std::old_io::util::{NullReader, NullWriter};
use std::io::{Cursor, sink};
use client::data::message::Message;
use client::test::buf_empty;
#[cfg(feature = "encode")] use encoding::{DecoderTrap, Encoding};
#[cfg(feature = "encode")] use encoding::all::{ISO_8859_15, UTF_8};
#[test]
#[cfg(not(feature = "encode"))]
fn send() {
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(
Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("Testing!"))
).is_ok());
let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
let data = String::from_utf8(conn.writer().to_vec()).unwrap();
assert_eq!(&data[..], "PRIVMSG test :Testing!\r\n");
}
@ -265,20 +266,20 @@ mod test {
#[cfg(not(feature = "encode"))]
fn send_str() {
let exp = "PRIVMSG test :Testing!\r\n";
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(exp).is_ok());
let data = String::from_utf8(conn.writer().get_ref().to_vec()).unwrap();
let data = String::from_utf8(conn.writer().to_vec()).unwrap();
assert_eq!(&data[..], exp);
}
#[test]
#[cfg(feature = "encode")]
fn send_utf8() {
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(
Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "UTF-8"
).is_ok());
let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
let data = UTF_8.decode(&conn.writer(), DecoderTrap::Strict).unwrap();
assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
}
@ -286,20 +287,20 @@ mod test {
#[cfg(feature = "encode")]
fn send_utf8_str() {
let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(exp, "UTF-8").is_ok());
let data = UTF_8.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
let data = UTF_8.decode(&conn.writer(), DecoderTrap::Strict).unwrap();
assert_eq!(&data[..], exp);
}
#[test]
#[cfg(feature = "encode")]
fn send_iso885915() {
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(
Message::new(None, "PRIVMSG", Some(vec!["test"]), Some("€ŠšŽžŒœŸ")), "l9"
).is_ok());
let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
let data = ISO_8859_15.decode(&conn.writer(), DecoderTrap::Strict).unwrap();
assert_eq!(&data[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
}
@ -307,9 +308,9 @@ mod test {
#[cfg(feature = "encode")]
fn send_iso885915_str() {
let exp = "PRIVMSG test :€ŠšŽžŒœŸ\r\n";
let conn = Connection::new(NullReader, MemWriter::new());
let conn = Connection::new(buf_empty(), Vec::new());
assert!(conn.send(exp, "l9").is_ok());
let data = ISO_8859_15.decode(conn.writer().get_ref(), DecoderTrap::Strict).unwrap();
let data = ISO_8859_15.decode(&conn.writer(), DecoderTrap::Strict).unwrap();
assert_eq!(&data[..], exp);
}
@ -317,7 +318,7 @@ mod test {
#[cfg(not(feature = "encode"))]
fn recv() {
let conn = Connection::new(
MemReader::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec()), NullWriter
Cursor::new("PRIVMSG test :Testing!\r\n".as_bytes().to_vec()), sink()
);
assert_eq!(&conn.recv().unwrap()[..], "PRIVMSG test :Testing!\r\n");
}
@ -326,7 +327,7 @@ mod test {
#[cfg(feature = "encode")]
fn recv_utf8() {
let conn = Connection::new(
MemReader::new(b"PRIVMSG test :Testing!\r\n".to_vec()), NullWriter
Cursor::new(b"PRIVMSG test :Testing!\r\n".to_vec()), sink()
);
assert_eq!(&conn.recv("UTF-8").unwrap()[..], "PRIVMSG test :Testing!\r\n");
}
@ -335,13 +336,13 @@ mod test {
#[cfg(feature = "encode")]
fn recv_iso885915() {
let conn = Connection::new(
MemReader::new({
Cursor::new({
let mut vec = Vec::new();
vec.push_all(b"PRIVMSG test :");
vec.push_all(&[0xA4, 0xA6, 0xA8, 0xB4, 0xB8, 0xBC, 0xBD, 0xBE]);
vec.push_all(b"\r\n");
vec
}), NullWriter
}), sink()
);
assert_eq!(&conn.recv("l9").unwrap()[..], "PRIVMSG test :€ŠšŽžŒœŸ\r\n");
}

View file

@ -1,6 +1,7 @@
//! Enumeration of all available client commands.
#![stable]
use std::old_io::{InvalidInput, IoError, IoResult};
use std::io::{Error, ErrorKind, Result};
use std::result::Result as StdResult;
use std::str::FromStr;
use client::data::message::{Message, ToMessage};
@ -363,7 +364,7 @@ impl ToMessage for Command {
impl Command {
/// Converts a Message into a Command.
#[stable]
pub fn from_message(m: &Message) -> IoResult<Command> {
pub fn from_message(m: &Message) -> Result<Command> {
Ok(if let "PASS" = &m.command[..] {
match m.suffix {
Some(ref suffix) => {
@ -1081,7 +1082,7 @@ impl Command {
/// Converts a potential Message result into a potential Command result.
#[unstable = "This feature is still relatively new."]
pub fn from_message_io(m: IoResult<Message>) -> IoResult<Command> {
pub fn from_message_io(m: Result<Message>) -> Result<Command> {
m.and_then(|msg| Command::from_message(&msg))
}
}
@ -1137,7 +1138,7 @@ impl CapSubCommand {
impl FromStr for CapSubCommand {
type Err = &'static str;
fn from_str(s: &str) -> Result<CapSubCommand, &'static str> {
fn from_str(s: &str) -> StdResult<CapSubCommand, &'static str> {
match s {
"LS" => Ok(CapSubCommand::LS),
"LIST" => Ok(CapSubCommand::LIST),
@ -1152,10 +1153,6 @@ impl FromStr for CapSubCommand {
}
/// Produces an invalid_input IoError.
fn invalid_input() -> IoError {
IoError {
kind: InvalidInput,
desc: "Failed to parse malformed message as command.",
detail: None
}
fn invalid_input() -> Error {
Error::new(ErrorKind::InvalidInput, "Failed to parse malformed message as command.", None)
}

View file

@ -2,9 +2,10 @@
#![stable]
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::error::Error;
use std::old_io::fs::File;
use std::old_io::{InvalidInput, IoError, IoResult};
use std::error::Error as StdError;
use std::fs::File;
use std::io::prelude::*;
use std::io::{Error, ErrorKind, Result};
use rustc_serialize::json::decode;
/// Configuration data.
@ -64,19 +65,19 @@ pub struct Config {
impl Config {
/// Loads a JSON configuration from the desired path.
#[stable]
pub fn load(path: Path) -> IoResult<Config> {
pub fn load(path: Path) -> Result<Config> {
let mut file = try!(File::open(&path));
let data = try!(file.read_to_string());
decode(&data[..]).map_err(|e| IoError {
kind: InvalidInput,
desc: "Failed to decode configuration file.",
detail: Some(e.description().to_owned()),
})
let mut data = String::new();
try!(file.read_to_string(&mut data));
decode(&data[..]).map_err(|e|
Error::new(ErrorKind::InvalidInput, "Failed to decode configuration file.",
Some(e.description().to_owned()))
)
}
/// Loads a JSON configuration using the string as a UTF-8 path.
#[stable]
pub fn load_utf8(path: &str) -> IoResult<Config> {
pub fn load_utf8(path: &str) -> Result<Config> {
Config::load(Path::new(path))
}

View file

@ -10,19 +10,16 @@ pub use client::data::user::{AccessLevel, User};
pub mod kinds {
//! Trait definitions of appropriate Writers and Buffers for use with this library.
#![stable]
use std::io::prelude::*;
/// Trait describing all possible Writers for this library.
#[stable]
pub trait IrcWriter: Writer + Sized + Send + 'static {}
impl<T> IrcWriter for T where T: Writer + Sized + Send + 'static {}
pub trait IrcWrite: Write + Sized + Send + 'static {}
impl<T> IrcWrite for T where T: Write + Sized + Send + 'static {}
/// Trait describing all possible Readers for this library.
#[stable]
pub trait IrcReader: Buffer + Sized + Send + 'static {}
impl<T> IrcReader for T where T: Buffer + Sized + Send + 'static {}
/// Trait describing all possible Streams for this library.
#[unstable = "May be removed."]
pub trait IrcStream: IrcWriter + IrcReader {}
impl<T> IrcStream for T where T: IrcWriter + IrcReader {}
pub trait IrcRead: BufRead + Sized + Send + 'static {}
impl<T> IrcRead for T where T: BufRead + Sized + Send + 'static {}
}
pub mod command;

View file

@ -12,5 +12,14 @@ pub mod prelude {
pub use client::server::{IrcServer, Server};
pub use client::server::utils::ServerExt;
pub use client::data::{Command, Config, Message, Response, ToMessage};
pub use client::data::kinds::{IrcReader, IrcWriter};
pub use client::data::kinds::{IrcRead, IrcWrite};
}
#[cfg(test)]
pub mod test {
use std::io::{BufReader, Empty, empty};
pub fn buf_empty() -> BufReader<Empty> {
BufReader::new(empty())
}
}

View file

@ -4,13 +4,13 @@
#![stable]
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::old_io::{BufferedReader, BufferedWriter, IoError, IoErrorKind, IoResult};
use std::io::{BufReader, BufWriter, Error, ErrorKind, Result};
use std::sync::{Mutex, RwLock};
use std::iter::Map;
use client::conn::{Connection, NetStream};
use client::data::{Command, Config, Message, Response, User};
use client::data::Command::{JOIN, NICK, NICKSERV, PONG, MODE};
use client::data::kinds::{IrcReader, IrcWriter};
use client::data::kinds::{IrcRead, IrcWrite};
#[cfg(feature = "ctcp")] use time::now;
pub mod utils;
@ -23,7 +23,7 @@ pub trait Server<'a, T, U> {
fn config(&self) -> &Config;
/// Sends a Command to this Server.
#[stable]
fn send(&self, command: Command) -> IoResult<()>;
fn send(&self, command: Command) -> Result<()>;
/// Gets an Iterator over Messages received by this Server.
#[stable]
fn iter(&'a self) -> ServerIterator<'a, T, U>;
@ -38,7 +38,7 @@ pub trait Server<'a, T, U> {
/// A thread-safe implementation of an IRC Server connection.
#[stable]
pub struct IrcServer<T: IrcReader, U: IrcWriter> {
pub struct IrcServer<T: IrcRead, U: IrcWrite> {
/// The thread-safe IRC connection.
conn: Connection<T, U>,
/// The configuration used with this connection.
@ -51,21 +51,21 @@ pub struct IrcServer<T: IrcReader, U: IrcWriter> {
/// An IrcServer over a buffered NetStream.
#[stable]
pub type NetIrcServer = IrcServer<BufferedReader<NetStream>, BufferedWriter<NetStream>>;
pub type NetIrcServer = IrcServer<BufReader<NetStream>, BufWriter<NetStream>>;
#[stable]
impl IrcServer<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
impl IrcServer<BufReader<NetStream>, BufWriter<NetStream>> {
/// Creates a new IRC Server connection from the configuration at the specified path,
/// connecting immediately.
#[stable]
pub fn new(config: &str) -> IoResult<NetIrcServer> {
pub fn new(config: &str) -> Result<NetIrcServer> {
IrcServer::from_config(try!(Config::load_utf8(config)))
}
/// Creates a new IRC server connection from the specified configuration, connecting
/// immediately.
#[stable]
pub fn from_config(config: Config) -> IoResult<NetIrcServer> {
pub fn from_config(config: Config) -> Result<NetIrcServer> {
let conn = try!(if config.use_ssl() {
Connection::connect_ssl(config.server(), config.port())
} else {
@ -77,23 +77,23 @@ impl IrcServer<BufferedReader<NetStream>, BufferedWriter<NetStream>> {
/// Reconnects to the IRC server.
#[stable]
pub fn reconnect(&self) -> IoResult<()> {
pub fn reconnect(&self) -> Result<()> {
self.conn.reconnect(self.config().server(), self.config.port())
}
}
impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for IrcServer<T, U> {
impl<'a, T: IrcRead, U: IrcWrite> Server<'a, T, U> for IrcServer<T, U> {
fn config(&self) -> &Config {
&self.config
}
#[cfg(feature = "encode")]
fn send(&self, cmd: Command) -> IoResult<()> {
fn send(&self, cmd: Command) -> Result<()> {
self.conn.send(cmd, self.config.encoding())
}
#[cfg(not(feature = "encode"))]
fn send(&self, cmd: Command) -> IoResult<()> {
fn send(&self, cmd: Command) -> Result<()> {
self.conn.send(cmd)
}
@ -118,7 +118,7 @@ impl<'a, T: IrcReader, U: IrcWriter> Server<'a, T, U> for IrcServer<T, U> {
}
#[stable]
impl<T: IrcReader, U: IrcWriter> IrcServer<T, U> {
impl<T: IrcRead, U: IrcWrite> IrcServer<T, U> {
/// Creates an IRC server from the specified configuration, and any arbitrary Connection.
#[stable]
pub fn from_connection(config: Config, conn: Connection<T, U>) -> IrcServer<T, U> {
@ -264,16 +264,16 @@ impl<T: IrcReader, U: IrcWriter> IrcServer<T, U> {
/// An Iterator over an IrcServer's incoming Messages.
#[stable]
pub struct ServerIterator<'a, T: IrcReader, U: IrcWriter> {
pub struct ServerIterator<'a, T: IrcRead, U: IrcWrite> {
server: &'a IrcServer<T, U>
}
/// An Iterator over an IrcServer's incoming Commands.
pub type ServerCmdIterator<'a, T, U> =
Map<ServerIterator<'a, T, U>, fn(IoResult<Message>) -> IoResult<Command>>;
Map<ServerIterator<'a, T, U>, fn(Result<Message>) -> Result<Command>>;
#[unstable = "Design is liable to change to accomodate new functionality."]
impl<'a, T: IrcReader, U: IrcWriter> ServerIterator<'a, T, U> {
impl<'a, T: IrcRead, U: IrcWrite> ServerIterator<'a, T, U> {
/// Creates a new ServerIterator for the desired IrcServer.
#[unstable = "Design is liable to change to accomodate new functionality."]
pub fn new(server: &IrcServer<T, U>) -> ServerIterator<T, U> {
@ -282,36 +282,35 @@ impl<'a, T: IrcReader, U: IrcWriter> ServerIterator<'a, T, U> {
/// Gets the next line from the connection.
#[cfg(feature = "encode")]
fn get_next_line(&self) -> IoResult<String> {
fn get_next_line(&self) -> Result<String> {
self.server.conn.recv(self.server.config.encoding())
}
/// Gets the next line from the connection.
#[cfg(not(feature = "encode"))]
fn get_next_line(&self) -> IoResult<String> {
fn get_next_line(&self) -> Result<String> {
self.server.conn.recv()
}
}
impl<'a, T: IrcReader, U: IrcWriter> Iterator for ServerIterator<'a, T, U> {
impl<'a, T: IrcRead, U: IrcWrite> Iterator for ServerIterator<'a, T, U> {
#[stable]
type Item = IoResult<Message>;
fn next(&mut self) -> Option<IoResult<Message>> {
type Item = Result<Message>;
fn next(&mut self) -> Option<Result<Message>> {
let res = self.get_next_line().and_then(|msg|
match msg.parse() {
Ok(msg) => {
self.server.handle_message(&msg);
Ok(msg)
},
Err(m) => Err(IoError {
kind: IoErrorKind::InvalidInput,
desc: "Failed to parse message.",
detail: Some(format!("{} (Message: {})", m, msg))
})
Err(m) => Err(Error::new(ErrorKind::InvalidInput, "Failed to parse message.",
Some(format!("{} (Message: {})", m, msg))))
}
);
match res {
Err(ref err) if err.kind == IoErrorKind::EndOfFile => None,
Err(ref err) if err.kind() == ErrorKind::ConnectionAborted => None,
Err(ref err) if err.kind() == ErrorKind::ConnectionReset => None,
Err(ref err) if err.description() == "EOF" => None,
_ => Some(res)
}
}
@ -321,13 +320,13 @@ impl<'a, T: IrcReader, U: IrcWriter> Iterator for ServerIterator<'a, T, U> {
mod test {
use super::{IrcServer, Server};
use std::default::Default;
use std::old_io::MemReader;
use std::old_io::util::{NullReader, NullWriter};
use std::io::{Cursor, sink};
use client::conn::Connection;
use client::data::{Config, User};
use client::data::command::Command::PRIVMSG;
use client::data::kinds::IrcReader;
use client::data::kinds::IrcRead;
use client::data::message::ToMessage;
use client::test::buf_empty;
pub fn test_config() -> Config {
Config {
@ -341,7 +340,7 @@ mod test {
}
}
pub fn get_server_value<T: IrcReader>(server: IrcServer<T, Vec<u8>>) -> String {
pub fn get_server_value<T: IrcRead>(server: IrcServer<T, Vec<u8>>) -> String {
let vec = server.conn().writer().clone();
String::from_utf8(vec).unwrap()
}
@ -351,7 +350,7 @@ mod test {
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
:test!test@test JOIN #test\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(exp.as_bytes().to_vec()), NullWriter
Cursor::new(exp.as_bytes().to_vec()), sink()
));
let mut messages = String::new();
for message in server.iter() {
@ -365,7 +364,7 @@ mod test {
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
JOIN #test\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(exp.as_bytes().to_vec()), NullWriter
Cursor::new(exp.as_bytes().to_vec()), sink()
));
let mut messages = String::new();
for command in server.iter_cmd() {
@ -378,7 +377,7 @@ mod test {
fn handle_message() {
let value = "PING :irc.test.net\r\n:irc.test.net 376 test :End of /MOTD command.\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -395,7 +394,7 @@ mod test {
channels: Some(vec![format!("#test"), format!("#test2")]),
.. Default::default()
}, Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -413,7 +412,7 @@ mod test {
channels: Some(vec![format!("#test"), format!("#test2")]),
.. Default::default()
}, Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -426,7 +425,7 @@ mod test {
fn nickname_in_use() {
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -440,7 +439,7 @@ mod test {
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
:irc.pdgn.co 433 * test2 :Nickname is already in use.\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -450,7 +449,7 @@ mod test {
#[test]
fn send() {
let server = IrcServer::from_connection(test_config(), Connection::new(
NullReader, Vec::new()
buf_empty(), Vec::new()
));
assert!(server.send(PRIVMSG(format!("#test"), format!("Hi there!"))).is_ok());
assert_eq!(&get_server_value(server)[..], "PRIVMSG #test :Hi there!\r\n");
@ -461,7 +460,7 @@ mod test {
fn user_tracking_names() {
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), NullWriter
Cursor::new(value.as_bytes().to_vec()), sink()
));
for message in server.iter() {
println!("{:?}", message);
@ -476,7 +475,7 @@ mod test {
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
:test2!test@test JOIN #test\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), NullWriter
Cursor::new(value.as_bytes().to_vec()), sink()
));
for message in server.iter() {
println!("{:?}", message);
@ -491,7 +490,7 @@ mod test {
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
:owner!test@test PART #test\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), NullWriter
Cursor::new(value.as_bytes().to_vec()), sink()
));
for message in server.iter() {
println!("{:?}", message);
@ -506,7 +505,7 @@ mod test {
let value = ":irc.test.net 353 test = #test :+test ~owner &admin\r\n\
:test!test@test MODE #test +o test\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), NullWriter
Cursor::new(value.as_bytes().to_vec()), sink()
));
for message in server.iter() {
println!("{:?}", message);
@ -529,7 +528,7 @@ mod test {
fn finger_response() {
let value = ":test!test@test PRIVMSG test :\u{001}FINGER\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -543,7 +542,7 @@ mod test {
fn version_response() {
let value = ":test!test@test PRIVMSG test :\u{001}VERSION\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -557,7 +556,7 @@ mod test {
fn source_response() {
let value = ":test!test@test PRIVMSG test :\u{001}SOURCE\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -572,7 +571,7 @@ mod test {
fn ctcp_ping_response() {
let value = ":test!test@test PRIVMSG test :\u{001}PING test\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -585,7 +584,7 @@ mod test {
fn time_response() {
let value = ":test!test@test PRIVMSG test :\u{001}TIME\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);
@ -600,7 +599,7 @@ mod test {
fn user_info_response() {
let value = ":test!test@test PRIVMSG test :\u{001}USERINFO\u{001}\r\n";
let server = IrcServer::from_connection(test_config(), Connection::new(
MemReader::new(value.as_bytes().to_vec()), Vec::new()
Cursor::new(value.as_bytes().to_vec()), Vec::new()
));
for message in server.iter() {
println!("{:?}", message);

View file

@ -1,12 +1,12 @@
//! Utilities and shortcuts for working with IRC servers.
#![stable]
use std::old_io::IoResult;
use std::io::Result;
use std::borrow::ToOwned;
use client::data::Command::{CAP, INVITE, JOIN, KICK, KILL, MODE, NICK, NOTICE};
use client::data::Command::{OPER, PASS, PONG, PRIVMSG, QUIT, SAMODE, SANICK, TOPIC, USER};
use client::data::command::CapSubCommand::{END, REQ};
use client::data::kinds::{IrcReader, IrcWriter};
use client::data::kinds::{IrcRead, IrcWrite};
#[cfg(feature = "ctcp")] use time::get_time;
use client::server::Server;
@ -15,7 +15,7 @@ use client::server::Server;
pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a NICK and USER to identify.
#[unstable = "Capabilities requests may be moved outside of identify."]
fn identify(&self) -> IoResult<()> {
fn identify(&self) -> Result<()> {
// We'll issue a CAP REQ for multi-prefix support to improve access level tracking.
try!(self.send(CAP(None, REQ, None, Some("multi-prefix".to_owned()))));
try!(self.send(CAP(None, END, None, None))); // Then, send a CAP END to end the negotiation.
@ -30,25 +30,25 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a PONG with the specified message.
#[stable]
fn send_pong(&self, msg: &str) -> IoResult<()> {
fn send_pong(&self, msg: &str) -> Result<()> {
self.send(PONG(msg.to_owned(), None))
}
/// Joins the specified channel or chanlist.
#[stable]
fn send_join(&self, chanlist: &str) -> IoResult<()> {
fn send_join(&self, chanlist: &str) -> Result<()> {
self.send(JOIN(chanlist.to_owned(), None))
}
/// Attempts to oper up using the specified username and password.
#[stable]
fn send_oper(&self, username: &str, password: &str) -> IoResult<()> {
fn send_oper(&self, username: &str, password: &str) -> Result<()> {
self.send(OPER(username.to_owned(), password.to_owned()))
}
/// Sends a message to the specified target.
#[stable]
fn send_privmsg(&self, target: &str, message: &str) -> IoResult<()> {
fn send_privmsg(&self, target: &str, message: &str) -> Result<()> {
for line in message.split("\r\n") {
try!(self.send(PRIVMSG(target.to_owned(), line.to_owned())))
}
@ -57,7 +57,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a notice to the specified target.
#[stable]
fn send_notice(&self, target: &str, message: &str) -> IoResult<()> {
fn send_notice(&self, target: &str, message: &str) -> Result<()> {
for line in message.split("\r\n") {
try!(self.send(NOTICE(target.to_owned(), line.to_owned())))
}
@ -67,7 +67,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sets the topic of a channel or requests the current one.
/// If `topic` is an empty string, it won't be included in the message.
#[unstable = "Design may change."]
fn send_topic(&self, channel: &str, topic: &str) -> IoResult<()> {
fn send_topic(&self, channel: &str, topic: &str) -> Result<()> {
self.send(TOPIC(channel.to_owned(), if topic.len() == 0 {
None
} else {
@ -77,14 +77,14 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Kills the target with the provided message.
#[stable]
fn send_kill(&self, target: &str, message: &str) -> IoResult<()> {
fn send_kill(&self, target: &str, message: &str) -> Result<()> {
self.send(KILL(target.to_owned(), message.to_owned()))
}
/// Kicks the listed nicknames from the listed channels with a comment.
/// If `message` is an empty string, it won't be included in the message.
#[unstable = "Design may change."]
fn send_kick(&self, chanlist: &str, nicklist: &str, message: &str) -> IoResult<()> {
fn send_kick(&self, chanlist: &str, nicklist: &str, message: &str) -> Result<()> {
self.send(KICK(chanlist.to_owned(), nicklist.to_owned(), if message.len() == 0 {
None
} else {
@ -95,7 +95,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Changes the mode of the target.
/// If `modeparmas` is an empty string, it won't be included in the message.
#[unstable = "Design may change."]
fn send_mode(&self, target: &str, mode: &str, modeparams: &str) -> IoResult<()> {
fn send_mode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()> {
self.send(MODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 {
None
} else {
@ -106,7 +106,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Changes the mode of the target by force.
/// If `modeparams` is an empty string, it won't be included in the message.
#[unstable = "Design may change."]
fn send_samode(&self, target: &str, mode: &str, modeparams: &str) -> IoResult<()> {
fn send_samode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()> {
self.send(SAMODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 {
None
} else {
@ -116,20 +116,20 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Forces a user to change from the old nickname to the new nickname.
#[stable]
fn send_sanick(&self, old_nick: &str, new_nick: &str) -> IoResult<()> {
fn send_sanick(&self, old_nick: &str, new_nick: &str) -> Result<()> {
self.send(SANICK(old_nick.to_owned(), new_nick.to_owned()))
}
/// Invites a user to the specified channel.
#[stable]
fn send_invite(&self, nick: &str, chan: &str) -> IoResult<()> {
fn send_invite(&self, nick: &str, chan: &str) -> Result<()> {
self.send(INVITE(nick.to_owned(), chan.to_owned()))
}
/// Quits the server entirely with a message.
/// This defaults to `Powered by Rust.` if none is specified.
#[unstable = "Design may change."]
fn send_quit(&self, msg: &str) -> IoResult<()> {
fn send_quit(&self, msg: &str) -> Result<()> {
self.send(QUIT(Some(if msg.len() == 0 {
"Powered by Rust.".to_owned()
} else {
@ -141,7 +141,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_ctcp(&self, target: &str, msg: &str) -> IoResult<()> {
fn send_ctcp(&self, target: &str, msg: &str) -> Result<()> {
self.send_privmsg(target, &format!("\u{001}{}\u{001}", msg)[..])
}
@ -149,7 +149,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_action(&self, target: &str, msg: &str) -> IoResult<()> {
fn send_action(&self, target: &str, msg: &str) -> Result<()> {
self.send_ctcp(target, &format!("ACTION {}", msg)[..])
}
@ -157,7 +157,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_finger(&self, target: &str) -> IoResult<()> {
fn send_finger(&self, target: &str) -> Result<()> {
self.send_ctcp(target, "FINGER")
}
@ -165,7 +165,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_version(&self, target: &str) -> IoResult<()> {
fn send_version(&self, target: &str) -> Result<()> {
self.send_ctcp(target, "VERSION")
}
@ -173,7 +173,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_source(&self, target: &str) -> IoResult<()> {
fn send_source(&self, target: &str) -> Result<()> {
self.send_ctcp(target, "SOURCE")
}
@ -181,7 +181,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_user_info(&self, target: &str) -> IoResult<()> {
fn send_user_info(&self, target: &str) -> Result<()> {
self.send_ctcp(target, "USERINFO")
}
@ -189,7 +189,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_ctcp_ping(&self, target: &str) -> IoResult<()> {
fn send_ctcp_ping(&self, target: &str) -> Result<()> {
let time = get_time();
self.send_ctcp(target, &format!("PING {}.{}", time.sec, time.nsec)[..])
}
@ -198,27 +198,27 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// This requires the CTCP feature to be enabled.
#[stable]
#[cfg(feature = "ctcp")]
fn send_time(&self, target: &str) -> IoResult<()> {
fn send_time(&self, target: &str) -> Result<()> {
self.send_ctcp(target, "TIME")
}
}
impl<'a, T: IrcReader, U: IrcWriter, K: Server<'a, T, U>> ServerExt<'a, T, U> for K {}
impl<'a, T: IrcRead, U: IrcWrite, K: Server<'a, T, U>> ServerExt<'a, T, U> for K {}
#[cfg(test)]
mod test {
use super::ServerExt;
use std::default::Default;
use std::old_io::util::NullReader;
use client::conn::Connection;
use client::data::Config;
use client::server::IrcServer;
use client::server::test::{get_server_value, test_config};
use client::test::buf_empty;
#[test]
fn identify() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.identify().unwrap();
assert_eq!(&get_server_value(server)[..],
"CAP REQ :multi-prefix\r\nCAP END\r\nNICK :test\r\nUSER test 0 * :test\r\n");
@ -230,7 +230,7 @@ mod test {
nickname: Some(format!("test")),
password: Some(format!("password")),
.. Default::default()
}, Connection::new(NullReader, Vec::new()));
}, Connection::new(buf_empty(), Vec::new()));
server.identify().unwrap();
assert_eq!(&get_server_value(server)[..], "CAP REQ :multi-prefix\r\nCAP END\r\n\
PASS :password\r\nNICK :test\r\nUSER test 0 * :test\r\n");
@ -239,7 +239,7 @@ mod test {
#[test]
fn send_pong() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_pong("irc.test.net").unwrap();
assert_eq!(&get_server_value(server)[..], "PONG :irc.test.net\r\n");
}
@ -247,7 +247,7 @@ mod test {
#[test]
fn send_join() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_join("#test,#test2,#test3").unwrap();
assert_eq!(&get_server_value(server)[..], "JOIN #test,#test2,#test3\r\n");
}
@ -255,7 +255,7 @@ mod test {
#[test]
fn send_oper() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_oper("test", "test").unwrap();
assert_eq!(&get_server_value(server)[..], "OPER test :test\r\n");
}
@ -263,7 +263,7 @@ mod test {
#[test]
fn send_privmsg() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_privmsg("#test", "Hi, everybody!").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG #test :Hi, everybody!\r\n");
}
@ -271,7 +271,7 @@ mod test {
#[test]
fn send_notice() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_notice("#test", "Hi, everybody!").unwrap();
assert_eq!(&get_server_value(server)[..], "NOTICE #test :Hi, everybody!\r\n");
}
@ -279,7 +279,7 @@ mod test {
#[test]
fn send_topic_no_topic() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_topic("#test", "").unwrap();
assert_eq!(&get_server_value(server)[..], "TOPIC #test\r\n");
}
@ -287,7 +287,7 @@ mod test {
#[test]
fn send_topic() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_topic("#test", "Testing stuff.").unwrap();
assert_eq!(&get_server_value(server)[..], "TOPIC #test :Testing stuff.\r\n");
}
@ -295,7 +295,7 @@ mod test {
#[test]
fn send_kill() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_kill("test", "Testing kills.").unwrap();
assert_eq!(&get_server_value(server)[..], "KILL test :Testing kills.\r\n");
}
@ -303,7 +303,7 @@ mod test {
#[test]
fn send_kick_no_message() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_kick("#test", "test", "").unwrap();
assert_eq!(&get_server_value(server)[..], "KICK #test test\r\n");
}
@ -311,7 +311,7 @@ mod test {
#[test]
fn send_kick() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_kick("#test", "test", "Testing kicks.").unwrap();
assert_eq!(&get_server_value(server)[..], "KICK #test test :Testing kicks.\r\n");
}
@ -319,7 +319,7 @@ mod test {
#[test]
fn send_mode_no_modeparams() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_mode("#test", "+i", "").unwrap();
assert_eq!(&get_server_value(server)[..], "MODE #test +i\r\n");
}
@ -327,7 +327,7 @@ mod test {
#[test]
fn send_mode() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_mode("#test", "+o", "test").unwrap();
assert_eq!(&get_server_value(server)[..], "MODE #test +o test\r\n");
}
@ -335,7 +335,7 @@ mod test {
#[test]
fn send_samode_no_modeparams() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_samode("#test", "+i", "").unwrap();
assert_eq!(&get_server_value(server)[..], "SAMODE #test +i\r\n");
}
@ -343,7 +343,7 @@ mod test {
#[test]
fn send_samode() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_samode("#test", "+o", "test").unwrap();
assert_eq!(&get_server_value(server)[..], "SAMODE #test +o test\r\n");
}
@ -351,7 +351,7 @@ mod test {
#[test]
fn send_sanick() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_sanick("test", "test2").unwrap();
assert_eq!(&get_server_value(server)[..], "SANICK test test2\r\n");
}
@ -359,7 +359,7 @@ mod test {
#[test]
fn send_invite() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_invite("test", "#test").unwrap();
assert_eq!(&get_server_value(server)[..], "INVITE test #test\r\n");
}
@ -368,7 +368,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_ctcp() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_ctcp("test", "MESSAGE").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}MESSAGE\u{001}\r\n");
}
@ -377,7 +377,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_action() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_action("test", "tests.").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}ACTION tests.\u{001}\r\n");
}
@ -386,7 +386,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_finger() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_finger("test").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}FINGER\u{001}\r\n");
}
@ -395,7 +395,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_version() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_version("test").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}VERSION\u{001}\r\n");
}
@ -404,7 +404,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_source() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_source("test").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}SOURCE\u{001}\r\n");
}
@ -413,7 +413,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_user_info() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_user_info("test").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}USERINFO\u{001}\r\n");
}
@ -422,7 +422,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_ctcp_ping() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_ctcp_ping("test").unwrap();
let val = get_server_value(server);
println!("{}", val);
@ -434,7 +434,7 @@ mod test {
#[cfg(feature = "ctcp")]
fn send_time() {
let server = IrcServer::from_connection(test_config(),
Connection::new(NullReader, Vec::new()));
Connection::new(buf_empty(), Vec::new()));
server.send_time("test").unwrap();
assert_eq!(&get_server_value(server)[..], "PRIVMSG test :\u{001}TIME\u{001}\r\n");
}

View file

@ -4,7 +4,7 @@
#![unstable]
#![warn(missing_docs)]
#![feature(collections, core, io, old_io, old_path)]
#![feature(collections, core, fs, io, net, old_path)]
#[cfg(feature = "ctcp")] extern crate time;
#[cfg(feature = "encode")] extern crate encoding;
extern crate "rustc-serialize" as rustc_serialize;