Use std::any::type_name
This commit is contained in:
parent
20d30d93c3
commit
53bb0a38f0
@ -1,9 +1,11 @@
|
|||||||
use std::any::{Any as StdAny, TypeId};
|
use std::any::{type_name, Any as StdAny, TypeId};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
pub trait Any: StdAny {
|
pub trait Any: StdAny {
|
||||||
fn type_id(&self) -> TypeId;
|
fn type_id(&self) -> TypeId;
|
||||||
|
|
||||||
|
fn type_name(&self) -> String;
|
||||||
|
|
||||||
fn box_clone(&self) -> Box<dyn Any>;
|
fn box_clone(&self) -> Box<dyn Any>;
|
||||||
|
|
||||||
/// This type may only be implemented by `rhai`.
|
/// This type may only be implemented by `rhai`.
|
||||||
@ -20,6 +22,10 @@ where
|
|||||||
TypeId::of::<T>()
|
TypeId::of::<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn type_name(&self) -> String {
|
||||||
|
type_name::<T>().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn box_clone(&self) -> Box<dyn Any> {
|
fn box_clone(&self) -> Box<dyn Any> {
|
||||||
Box::new(self.clone())
|
Box::new(self.clone())
|
||||||
|
@ -127,7 +127,6 @@ pub struct FnSpec {
|
|||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
/// A hashmap containing all functions known to the engine
|
/// A hashmap containing all functions known to the engine
|
||||||
pub fns: HashMap<FnSpec, Arc<FnIntExt>>,
|
pub fns: HashMap<FnSpec, Arc<FnIntExt>>,
|
||||||
pub type_names: HashMap<TypeId, String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum FnIntExt {
|
pub enum FnIntExt {
|
||||||
@ -164,7 +163,7 @@ impl Engine {
|
|||||||
.and_then(|b| {
|
.and_then(|b| {
|
||||||
b.downcast()
|
b.downcast()
|
||||||
.map(|b| *b)
|
.map(|b| *b)
|
||||||
.map_err(|a| EvalAltResult::ErrorMismatchOutputType(self.nice_type_name(a)))
|
.map_err(|a| EvalAltResult::ErrorMismatchOutputType((*a).type_name()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +201,7 @@ impl Engine {
|
|||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
let typenames = args
|
let typenames = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| self.nice_type_name((&**x).box_clone()))
|
.map(|x| (*(&**x).box_clone()).type_name())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
EvalAltResult::ErrorFunctionNotFound(format!("{} ({})", ident, typenames.join(",")))
|
EvalAltResult::ErrorFunctionNotFound(format!("{} ({})", ident, typenames.join(",")))
|
||||||
})
|
})
|
||||||
@ -239,13 +238,6 @@ impl Engine {
|
|||||||
// currently a no-op, exists for future extensibility
|
// currently a no-op, exists for future extensibility
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a type, providing a name for nice error messages.
|
|
||||||
pub fn register_type_name<T: Any>(&mut self, name: &str) {
|
|
||||||
self.register_type::<T>();
|
|
||||||
debug_println!("register type {}: {:?}", name, TypeId::of::<T>());
|
|
||||||
self.type_names.insert(TypeId::of::<T>(), name.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register a get function for a member of a registered type
|
/// Register a get function for a member of a registered type
|
||||||
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
||||||
where
|
where
|
||||||
@ -632,15 +624,6 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nice_type_name(&self, b: Box<dyn Any>) -> String {
|
|
||||||
let tid = <dyn Any as Any>::type_id(&*b);
|
|
||||||
if let Some(name) = self.type_names.get(&tid) {
|
|
||||||
name.to_string()
|
|
||||||
} else {
|
|
||||||
format!("<unknown> {:?}", b.type_id())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Evaluate a file
|
/// Evaluate a file
|
||||||
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -705,7 +688,7 @@ impl Engine {
|
|||||||
match x.downcast::<T>() {
|
match x.downcast::<T>() {
|
||||||
Ok(out) => Ok(*out),
|
Ok(out) => Ok(*out),
|
||||||
Err(a) => Err(EvalAltResult::ErrorMismatchOutputType(
|
Err(a) => Err(EvalAltResult::ErrorMismatchOutputType(
|
||||||
self.nice_type_name(a),
|
(*a).type_name(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -789,18 +772,6 @@ impl Engine {
|
|||||||
/// Register the default library. That means, numberic types, char, bool
|
/// Register the default library. That means, numberic types, char, bool
|
||||||
/// String, arithmetics and string concatenations.
|
/// String, arithmetics and string concatenations.
|
||||||
pub fn register_default_lib(engine: &mut Engine) {
|
pub fn register_default_lib(engine: &mut Engine) {
|
||||||
engine.register_type_name::<i32>("i32");
|
|
||||||
engine.register_type_name::<u32>("u32");
|
|
||||||
engine.register_type_name::<i64>("integer");
|
|
||||||
engine.register_type_name::<u64>("u64");
|
|
||||||
engine.register_type_name::<usize>("usize");
|
|
||||||
engine.register_type_name::<f32>("f32");
|
|
||||||
engine.register_type_name::<f64>("float");
|
|
||||||
engine.register_type_name::<String>("string");
|
|
||||||
engine.register_type_name::<char>("char");
|
|
||||||
engine.register_type_name::<bool>("boolean");
|
|
||||||
engine.register_type_name::<Vec<Box<dyn Any>>>("array");
|
|
||||||
|
|
||||||
macro_rules! reg_op {
|
macro_rules! reg_op {
|
||||||
($engine:expr, $x:expr, $op:expr, $( $y:ty ),*) => (
|
($engine:expr, $x:expr, $op:expr, $( $y:ty ),*) => (
|
||||||
$(
|
$(
|
||||||
@ -942,8 +913,7 @@ impl Engine {
|
|||||||
/// Make a new engine
|
/// Make a new engine
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
let mut engine = Engine {
|
let mut engine = Engine {
|
||||||
fns: HashMap::new(),
|
fns: HashMap::new()
|
||||||
type_names: HashMap::new(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Engine::register_default_lib(&mut engine);
|
Engine::register_default_lib(&mut engine);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use rhai::{Engine, EvalAltResult};
|
use rhai::{Engine, EvalAltResult, RegisterFn};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mismatched_op() {
|
fn test_mismatched_op() {
|
||||||
@ -7,7 +7,32 @@ fn test_mismatched_op() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
engine.eval::<i64>("60 + \"hello\""),
|
engine.eval::<i64>("60 + \"hello\""),
|
||||||
Err(EvalAltResult::ErrorFunctionNotFound(
|
Err(EvalAltResult::ErrorFunctionNotFound(
|
||||||
"+ (integer,string)".into()
|
"+ (i64,alloc::string::String)".into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mismatched_op_custom_type() {
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct TestStruct {
|
||||||
|
x: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestStruct {
|
||||||
|
fn new() -> TestStruct {
|
||||||
|
TestStruct { x: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
engine.register_type::<TestStruct>();
|
||||||
|
engine.register_fn("new_ts", TestStruct::new);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
engine.eval::<i64>("60 + new_ts()"),
|
||||||
|
Err(EvalAltResult::ErrorFunctionNotFound(
|
||||||
|
"+ (i64,mismatched_op::test_mismatched_op_custom_type::TestStruct)".into()
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user