Added Sized bounds on Self to make Server and ServerExt object-safe.

This commit is contained in:
Aaron Weiss 2015-06-16 16:04:37 -04:00
parent 3461dc0bc8
commit 83c38931bf
2 changed files with 29 additions and 26 deletions

View file

@ -21,7 +21,7 @@ pub trait Server<'a, T, U> {
/// Gets the configuration being used with this Server. /// Gets the configuration being used with this Server.
fn config(&self) -> &Config; fn config(&self) -> &Config;
/// Sends a Command to this Server. /// Sends a Command to this Server.
fn send<M: Into<Message>>(&self, message: M) -> Result<()>; fn send<M: Into<Message>>(&self, message: M) -> Result<()> where Self: Sized;
/// Gets an Iterator over Messages received by this Server. /// Gets an Iterator over Messages received by this Server.
fn iter(&'a self) -> ServerIterator<'a, T, U>; fn iter(&'a self) -> ServerIterator<'a, T, U>;
/// Gets an Iterator over Commands received by this Server. /// Gets an Iterator over Commands received by this Server.
@ -83,7 +83,7 @@ impl<'a, T: IrcRead, U: IrcWrite> Server<'a, T, U> for IrcServer<T, U> {
} }
#[cfg(not(feature = "encode"))] #[cfg(not(feature = "encode"))]
fn send<M: Into<Message>>(&self, msg: M) -> Result<()> { fn send<M: Into<Message>>(&self, msg: M) -> Result<()> where Self: Sized {
self.conn.send(msg) self.conn.send(msg)
} }

View file

@ -12,7 +12,7 @@ use client::server::Server;
/// Extensions for Server capabilities that make it easier to work directly with the protocol. /// Extensions for Server capabilities that make it easier to work directly with the protocol.
pub trait ServerExt<'a, T, U>: Server<'a, T, U> { pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a request for a list of server capabilities for a specific IRCv3 version. /// Sends a request for a list of server capabilities for a specific IRCv3 version.
fn send_cap_ls(&self, version: NegotiationVersion) -> Result<()> { fn send_cap_ls(&self, version: NegotiationVersion) -> Result<()> where Self: Sized {
self.send(CAP(None, LS, match version { self.send(CAP(None, LS, match version {
NegotiationVersion::V301 => None, NegotiationVersion::V301 => None,
NegotiationVersion::V302 => Some("302".to_owned()), NegotiationVersion::V302 => Some("302".to_owned()),
@ -20,7 +20,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Sends an IRCv3 capabilities request for the specified extensions. /// Sends an IRCv3 capabilities request for the specified extensions.
fn send_cap_req(&self, extensions: &[Capability]) -> Result<()> { fn send_cap_req(&self, extensions: &[Capability]) -> Result<()> where Self: Sized {
let append = |mut s: String, c| { s.push_str(c); s.push(' '); s }; let append = |mut s: String, c| { s.push_str(c); s.push(' '); s };
let mut exts = extensions.iter().map(|c| c.as_ref()).fold(String::new(), append); let mut exts = extensions.iter().map(|c| c.as_ref()).fold(String::new(), append);
let len = exts.len() - 1; let len = exts.len() - 1;
@ -29,7 +29,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Sends a CAP END, NICK and USER to identify. /// Sends a CAP END, NICK and USER to identify.
fn identify(&self) -> Result<()> { fn identify(&self) -> Result<()> where Self: Sized {
// Send a CAP END to signify that we're IRCv3-compliant (and to end negotiations!). // Send a CAP END to signify that we're IRCv3-compliant (and to end negotiations!).
try!(self.send(CAP(None, END, None, None))); try!(self.send(CAP(None, END, None, None)));
if self.config().password() != "" { if self.config().password() != "" {
@ -42,22 +42,22 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Sends a PONG with the specified message. /// Sends a PONG with the specified message.
fn send_pong(&self, msg: &str) -> Result<()> { fn send_pong(&self, msg: &str) -> Result<()> where Self: Sized {
self.send(PONG(msg.to_owned(), None)) self.send(PONG(msg.to_owned(), None))
} }
/// Joins the specified channel or chanlist. /// Joins the specified channel or chanlist.
fn send_join(&self, chanlist: &str) -> Result<()> { fn send_join(&self, chanlist: &str) -> Result<()> where Self: Sized {
self.send(JOIN(chanlist.to_owned(), None, None)) self.send(JOIN(chanlist.to_owned(), None, None))
} }
/// Attempts to oper up using the specified username and password. /// Attempts to oper up using the specified username and password.
fn send_oper(&self, username: &str, password: &str) -> Result<()> { fn send_oper(&self, username: &str, password: &str) -> Result<()> where Self: Sized {
self.send(OPER(username.to_owned(), password.to_owned())) self.send(OPER(username.to_owned(), password.to_owned()))
} }
/// Sends a message to the specified target. /// Sends a message to the specified target.
fn send_privmsg(&self, target: &str, message: &str) -> Result<()> { fn send_privmsg(&self, target: &str, message: &str) -> Result<()> where Self: Sized {
for line in message.split("\r\n") { for line in message.split("\r\n") {
try!(self.send(PRIVMSG(target.to_owned(), line.to_owned()))) try!(self.send(PRIVMSG(target.to_owned(), line.to_owned())))
} }
@ -65,7 +65,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Sends a notice to the specified target. /// Sends a notice to the specified target.
fn send_notice(&self, target: &str, message: &str) -> Result<()> { fn send_notice(&self, target: &str, message: &str) -> Result<()> where Self: Sized {
for line in message.split("\r\n") { for line in message.split("\r\n") {
try!(self.send(NOTICE(target.to_owned(), line.to_owned()))) try!(self.send(NOTICE(target.to_owned(), line.to_owned())))
} }
@ -74,7 +74,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sets the topic of a channel or requests the current one. /// 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. /// If `topic` is an empty string, it won't be included in the message.
fn send_topic(&self, channel: &str, topic: &str) -> Result<()> { fn send_topic(&self, channel: &str, topic: &str) -> Result<()> where Self: Sized {
self.send(TOPIC(channel.to_owned(), if topic.len() == 0 { self.send(TOPIC(channel.to_owned(), if topic.len() == 0 {
None None
} else { } else {
@ -83,13 +83,14 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Kills the target with the provided message. /// Kills the target with the provided message.
fn send_kill(&self, target: &str, message: &str) -> Result<()> { fn send_kill(&self, target: &str, message: &str) -> Result<()> where Self: Sized {
self.send(KILL(target.to_owned(), message.to_owned())) self.send(KILL(target.to_owned(), message.to_owned()))
} }
/// Kicks the listed nicknames from the listed channels with a comment. /// 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. /// If `message` is an empty string, it won't be included in the message.
fn send_kick(&self, chanlist: &str, nicklist: &str, message: &str) -> Result<()> { fn send_kick(&self, chanlist: &str, nicklist: &str, message: &str) -> Result<()>
where Self: Sized {
self.send(KICK(chanlist.to_owned(), nicklist.to_owned(), if message.len() == 0 { self.send(KICK(chanlist.to_owned(), nicklist.to_owned(), if message.len() == 0 {
None None
} else { } else {
@ -99,7 +100,8 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Changes the mode of the target. /// Changes the mode of the target.
/// If `modeparmas` is an empty string, it won't be included in the message. /// If `modeparmas` is an empty string, it won't be included in the message.
fn send_mode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()> { fn send_mode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()>
where Self: Sized {
self.send(MODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 { self.send(MODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 {
None None
} else { } else {
@ -109,7 +111,8 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Changes the mode of the target by force. /// Changes the mode of the target by force.
/// If `modeparams` is an empty string, it won't be included in the message. /// If `modeparams` is an empty string, it won't be included in the message.
fn send_samode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()> { fn send_samode(&self, target: &str, mode: &str, modeparams: &str) -> Result<()>
where Self: Sized {
self.send(SAMODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 { self.send(SAMODE(target.to_owned(), mode.to_owned(), if modeparams.len() == 0 {
None None
} else { } else {
@ -118,18 +121,18 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
} }
/// Forces a user to change from the old nickname to the new nickname. /// Forces a user to change from the old nickname to the new nickname.
fn send_sanick(&self, old_nick: &str, new_nick: &str) -> Result<()> { fn send_sanick(&self, old_nick: &str, new_nick: &str) -> Result<()> where Self: Sized {
self.send(SANICK(old_nick.to_owned(), new_nick.to_owned())) self.send(SANICK(old_nick.to_owned(), new_nick.to_owned()))
} }
/// Invites a user to the specified channel. /// Invites a user to the specified channel.
fn send_invite(&self, nick: &str, chan: &str) -> Result<()> { fn send_invite(&self, nick: &str, chan: &str) -> Result<()> where Self: Sized {
self.send(INVITE(nick.to_owned(), chan.to_owned())) self.send(INVITE(nick.to_owned(), chan.to_owned()))
} }
/// Quits the server entirely with a message. /// Quits the server entirely with a message.
/// This defaults to `Powered by Rust.` if none is specified. /// This defaults to `Powered by Rust.` if none is specified.
fn send_quit(&self, msg: &str) -> Result<()> { fn send_quit(&self, msg: &str) -> Result<()> where Self: Sized {
self.send(QUIT(Some(if msg.len() == 0 { self.send(QUIT(Some(if msg.len() == 0 {
"Powered by Rust.".to_owned() "Powered by Rust.".to_owned()
} else { } else {
@ -140,49 +143,49 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a CTCP-escaped message to the specified target. /// Sends a CTCP-escaped message to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_ctcp(&self, target: &str, msg: &str) -> Result<()> { fn send_ctcp(&self, target: &str, msg: &str) -> Result<()> where Self: Sized {
self.send_privmsg(target, &format!("\u{001}{}\u{001}", msg)[..]) self.send_privmsg(target, &format!("\u{001}{}\u{001}", msg)[..])
} }
/// Sends an action command to the specified target. /// Sends an action command to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_action(&self, target: &str, msg: &str) -> Result<()> { fn send_action(&self, target: &str, msg: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, &format!("ACTION {}", msg)[..]) self.send_ctcp(target, &format!("ACTION {}", msg)[..])
} }
/// Sends a finger request to the specified target. /// Sends a finger request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_finger(&self, target: &str) -> Result<()> { fn send_finger(&self, target: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, "FINGER") self.send_ctcp(target, "FINGER")
} }
/// Sends a version request to the specified target. /// Sends a version request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_version(&self, target: &str) -> Result<()> { fn send_version(&self, target: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, "VERSION") self.send_ctcp(target, "VERSION")
} }
/// Sends a source request to the specified target. /// Sends a source request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_source(&self, target: &str) -> Result<()> { fn send_source(&self, target: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, "SOURCE") self.send_ctcp(target, "SOURCE")
} }
/// Sends a user info request to the specified target. /// Sends a user info request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_user_info(&self, target: &str) -> Result<()> { fn send_user_info(&self, target: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, "USERINFO") self.send_ctcp(target, "USERINFO")
} }
/// Sends a finger request to the specified target. /// Sends a finger request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_ctcp_ping(&self, target: &str) -> Result<()> { fn send_ctcp_ping(&self, target: &str) -> Result<()> where Self: Sized {
let time = get_time(); let time = get_time();
self.send_ctcp(target, &format!("PING {}.{}", time.sec, time.nsec)[..]) self.send_ctcp(target, &format!("PING {}.{}", time.sec, time.nsec)[..])
} }
@ -190,7 +193,7 @@ pub trait ServerExt<'a, T, U>: Server<'a, T, U> {
/// Sends a time request to the specified target. /// Sends a time request to the specified target.
/// This requires the CTCP feature to be enabled. /// This requires the CTCP feature to be enabled.
#[cfg(feature = "ctcp")] #[cfg(feature = "ctcp")]
fn send_time(&self, target: &str) -> Result<()> { fn send_time(&self, target: &str) -> Result<()> where Self: Sized {
self.send_ctcp(target, "TIME") self.send_ctcp(target, "TIME")
} }
} }