From 66aa08ecddd0111f3cb5f0b2ee7a04d9a8bd2d74 Mon Sep 17 00:00:00 2001 From: Jonathan Reem Date: Tue, 6 Jan 2015 01:15:32 +0100 Subject: [PATCH] Make downcasting inherent methods on NetworkStream. --- src/net.rs | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/src/net.rs b/src/net.rs index 0abeb27a..b15d24c8 100644 --- a/src/net.rs +++ b/src/net.rs @@ -1,13 +1,12 @@ //! A collection of traits abstracting over Listeners and Streams. -use std::any::{Any, AnyRefExt}; -use std::boxed::BoxAny; +use std::any::Any; use std::fmt; use std::intrinsics::TypeId; use std::io::{IoResult, IoError, ConnectionAborted, InvalidInput, OtherIoError, Stream, Listener, Acceptor}; use std::io::net::ip::{SocketAddr, ToSocketAddr, Port}; use std::io::net::tcp::{TcpStream, TcpListener, TcpAcceptor}; -use std::mem::{self, transmute, transmute_copy}; +use std::mem; use std::raw::{self, TraitObject}; use uany::UnsafeAnyExt; @@ -105,46 +104,54 @@ impl<'a> Writer for &'a mut NetworkStream { fn flush(&mut self) -> IoResult<()> { (**self).flush() } } -impl UnsafeAnyExt for NetworkStream + Send { +impl UnsafeAnyExt for NetworkStream { unsafe fn downcast_ref_unchecked(&self) -> &T { - mem::transmute(mem::transmute::<&(NetworkStream + Send), + mem::transmute(mem::transmute::<&NetworkStream, raw::TraitObject>(self).data) } unsafe fn downcast_mut_unchecked(&mut self) -> &mut T { - mem::transmute(mem::transmute::<&mut (NetworkStream + Send), + mem::transmute(mem::transmute::<&mut NetworkStream, raw::TraitObject>(self).data) } - unsafe fn downcast_unchecked(self: Box) -> Box { - mem::transmute(mem::transmute::, + unsafe fn downcast_unchecked(self: Box) -> Box { + mem::transmute(mem::transmute::, 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] - fn is(self) -> bool { + pub fn is(&self) -> bool { self.get_type_id() == TypeId::of::() } + /// If the underlying type is T, get a reference to the contained data. #[inline] - fn downcast_ref(self) -> Option<&'a T> { + pub fn downcast_ref(&self) -> Option<&T> { if self.is::() { - unsafe { - // Get the raw representation of the trait object - let to: TraitObject = transmute_copy(&self); - // Extract the data pointer - Some(transmute(to.data)) - } + Some(unsafe { self.downcast_ref_unchecked() }) } else { None } } -} -impl BoxAny for Box { - fn downcast(self) -> Result, Box> { + /// If the underlying type is T, get a mutable reference to the contained + /// data. + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + Some(unsafe { self.downcast_mut_unchecked() }) + } else { + None + } + } + + /// If the underlying type is T, extract it. + pub fn downcast(self: Box) + -> Result, Box> { if self.is::() { Ok(unsafe { self.downcast_unchecked() }) } else { @@ -310,7 +317,7 @@ mod tests { fn test_downcast_box_stream() { let stream = box MockStream::new() as Box; - let mock = stream.downcast::().unwrap(); + let mock = stream.downcast::().ok().unwrap(); assert_eq!(mock, box MockStream::new()); }