Simplify reflection usage in Actor code.

The fixed version is shorter, and doesn't use unstable features.
This commit is contained in:
Eli Friedman 2015-08-30 19:01:15 -07:00
parent 9b2aa095f2
commit 5215b51b55
3 changed files with 15 additions and 63 deletions

View file

@ -6,13 +6,11 @@
use devtools_traits::PreciseTime; use devtools_traits::PreciseTime;
use rustc_serialize::json; use rustc_serialize::json;
use std::any::{Any, TypeId}; use std::any::Any;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::marker::Reflect; use std::mem::replace;
use std::mem::{replace, transmute};
use std::net::TcpStream; use std::net::TcpStream;
use std::raw::TraitObject;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[derive(PartialEq)] #[derive(PartialEq)]
@ -24,7 +22,7 @@ pub enum ActorMessageStatus {
/// A common trait for all devtools actors that encompasses an immutable name /// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors. /// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable /// TODO: ensure the name is immutable
pub trait Actor: Any { pub trait Actor: Any + ActorAsAny {
fn handle_message(&self, fn handle_message(&self,
registry: &ActorRegistry, registry: &ActorRegistry,
msg_type: &str, msg_type: &str,
@ -33,55 +31,14 @@ pub trait Actor: Any {
fn name(&self) -> String; fn name(&self) -> String;
} }
impl Actor + Send { trait ActorAsAny {
/// Returns true if the boxed type is the same as `T` fn actor_as_any(&self) -> &Any;
#[inline] fn actor_as_any_mut(&mut self) -> &mut Any;
pub fn is<T: Reflect + 'static>(&self) -> bool {
// Get TypeId of the type this function is instantiated with
let t = TypeId::of::<T>();
// Get TypeId of the type in the trait object
let boxed = self.get_type_id();
// Compare both TypeIds on equality
t == boxed
} }
/// Returns some reference to the boxed value if it is of type `T`, or impl<T: Actor> ActorAsAny for T {
/// `None` if it isn't. fn actor_as_any(&self) -> &Any { self }
#[inline] fn actor_as_any_mut(&mut self) -> &mut Any { self }
#[allow(unsafe_code)]
pub fn downcast_ref<T: Reflect + 'static>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute(self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
/// Returns some mutable reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
#[allow(unsafe_code)]
pub fn downcast_mut<T: Reflect + 'static>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute(self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
} }
/// A list of known, owned actors. /// A list of known, owned actors.
@ -179,15 +136,15 @@ impl ActorRegistry {
} }
/// Find an actor by registered name /// Find an actor by registered name
pub fn find<'a, T: Reflect + 'static>(&'a self, name: &str) -> &'a T { pub fn find<'a, T: Any>(&'a self, name: &str) -> &'a T {
let actor = self.actors.get(&name.to_string()).unwrap(); let actor = self.actors.get(&name.to_string()).unwrap();
actor.downcast_ref::<T>().unwrap() actor.actor_as_any().downcast_ref::<T>().unwrap()
} }
/// Find an actor by registered name /// Find an actor by registered name
pub fn find_mut<'a, T: Reflect + 'static>(&'a mut self, name: &str) -> &'a mut T { pub fn find_mut<'a, T: Any>(&'a mut self, name: &str) -> &'a mut T {
let actor = self.actors.get_mut(&name.to_string()).unwrap(); let actor = self.actors.get_mut(&name.to_string()).unwrap();
actor.downcast_mut::<T>().unwrap() actor.actor_as_any_mut().downcast_mut::<T>().unwrap()
} }
/// Attempt to process a message as directed by its `to` property. If the actor is not /// Attempt to process a message as directed by its `to` property. If the actor is not

View file

@ -17,9 +17,9 @@ use devtools_traits::EvaluateJSReply::{StringValue, BooleanValue, ActorValue};
use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg, PAGE_ERROR, CONSOLE_API}; use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg, PAGE_ERROR, CONSOLE_API};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use core::cell::RefCell;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use rustc_serialize::json::{self, Json, ToJson}; use rustc_serialize::json::{self, Json, ToJson};
use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::net::TcpStream; use std::net::TcpStream;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;

View file

@ -11,12 +11,8 @@
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(core)]
#![feature(custom_derive)] #![feature(custom_derive)]
#![feature(get_type_id)]
#![feature(plugin)] #![feature(plugin)]
#![feature(raw)]
#![feature(reflect_marker)]
#![plugin(serde_macros)] #![plugin(serde_macros)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
@ -25,7 +21,6 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate core;
extern crate devtools_traits; extern crate devtools_traits;
extern crate rustc_serialize; extern crate rustc_serialize;
extern crate ipc_channel; extern crate ipc_channel;