Make downcasting inherent methods on NetworkStream.
This commit is contained in:
49
src/net.rs
49
src/net.rs
@@ -1,13 +1,12 @@
|
|||||||
//! A collection of traits abstracting over Listeners and Streams.
|
//! A collection of traits abstracting over Listeners and Streams.
|
||||||
use std::any::{Any, AnyRefExt};
|
use std::any::Any;
|
||||||
use std::boxed::BoxAny;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::intrinsics::TypeId;
|
use std::intrinsics::TypeId;
|
||||||
use std::io::{IoResult, IoError, ConnectionAborted, InvalidInput, OtherIoError,
|
use std::io::{IoResult, IoError, ConnectionAborted, InvalidInput, OtherIoError,
|
||||||
Stream, Listener, Acceptor};
|
Stream, Listener, Acceptor};
|
||||||
use std::io::net::ip::{SocketAddr, ToSocketAddr, Port};
|
use std::io::net::ip::{SocketAddr, ToSocketAddr, Port};
|
||||||
use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor};
|
use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor};
|
||||||
use std::mem::{self, transmute, transmute_copy};
|
use std::mem;
|
||||||
use std::raw::{self, TraitObject};
|
use std::raw::{self, TraitObject};
|
||||||
|
|
||||||
use uany::UnsafeAnyExt;
|
use uany::UnsafeAnyExt;
|
||||||
@@ -105,46 +104,54 @@ impl<'a> Writer for &'a mut NetworkStream {
|
|||||||
fn flush(&mut self) -> IoResult<()> { (**self).flush() }
|
fn flush(&mut self) -> IoResult<()> { (**self).flush() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnsafeAnyExt for NetworkStream + Send {
|
impl UnsafeAnyExt for NetworkStream {
|
||||||
unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
|
unsafe fn downcast_ref_unchecked<T: 'static>(&self) -> &T {
|
||||||
mem::transmute(mem::transmute::<&(NetworkStream + Send),
|
mem::transmute(mem::transmute::<&NetworkStream,
|
||||||
raw::TraitObject>(self).data)
|
raw::TraitObject>(self).data)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
|
unsafe fn downcast_mut_unchecked<T: 'static>(&mut self) -> &mut T {
|
||||||
mem::transmute(mem::transmute::<&mut (NetworkStream + Send),
|
mem::transmute(mem::transmute::<&mut NetworkStream,
|
||||||
raw::TraitObject>(self).data)
|
raw::TraitObject>(self).data)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn downcast_unchecked<T: 'static>(self: Box<NetworkStream + Send>) -> Box<T> {
|
unsafe fn downcast_unchecked<T: 'static>(self: Box<NetworkStream>) -> Box<T> {
|
||||||
mem::transmute(mem::transmute::<Box<NetworkStream + Send>,
|
mem::transmute(mem::transmute::<Box<NetworkStream>,
|
||||||
raw::TraitObject>(self).data)
|
raw::TraitObject>(self).data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AnyRefExt<'a> for &'a (NetworkStream + 'static) {
|
impl NetworkStream {
|
||||||
|
/// Is the underlying type in this trait object a T?
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is<T: 'static>(self) -> bool {
|
pub fn is<T: 'static>(&self) -> bool {
|
||||||
self.get_type_id() == TypeId::of::<T>()
|
self.get_type_id() == TypeId::of::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the underlying type is T, get a reference to the contained data.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
|
pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
unsafe {
|
Some(unsafe { self.downcast_ref_unchecked() })
|
||||||
// Get the raw representation of the trait object
|
|
||||||
let to: TraitObject = transmute_copy(&self);
|
|
||||||
// Extract the data pointer
|
|
||||||
Some(transmute(to.data))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BoxAny for Box<NetworkStream + Send> {
|
/// If the underlying type is T, get a mutable reference to the contained
|
||||||
fn downcast<T: 'static>(self) -> Result<Box<T>, Box<NetworkStream + Send>> {
|
/// data.
|
||||||
|
#[inline]
|
||||||
|
pub fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T> {
|
||||||
|
if self.is::<T>() {
|
||||||
|
Some(unsafe { self.downcast_mut_unchecked() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the underlying type is T, extract it.
|
||||||
|
pub fn downcast<T: 'static>(self: Box<NetworkStream>)
|
||||||
|
-> Result<Box<T>, Box<NetworkStream>> {
|
||||||
if self.is::<T>() {
|
if self.is::<T>() {
|
||||||
Ok(unsafe { self.downcast_unchecked() })
|
Ok(unsafe { self.downcast_unchecked() })
|
||||||
} else {
|
} else {
|
||||||
@@ -310,7 +317,7 @@ mod tests {
|
|||||||
fn test_downcast_box_stream() {
|
fn test_downcast_box_stream() {
|
||||||
let stream = box MockStream::new() as Box<NetworkStream + Send>;
|
let stream = box MockStream::new() as Box<NetworkStream + Send>;
|
||||||
|
|
||||||
let mock = stream.downcast::<MockStream>().unwrap();
|
let mock = stream.downcast::<MockStream>().ok().unwrap();
|
||||||
assert_eq!(mock, box MockStream::new());
|
assert_eq!(mock, box MockStream::new());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user