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