Skip to content

Commit f7ce25b

Browse files
committed
refactor function interface, reduce amount of string cloning, happy cows
1 parent 2b2a451 commit f7ce25b

File tree

15 files changed

+595
-456
lines changed

15 files changed

+595
-456
lines changed

crates/bevy_mod_scripting_core/src/bindings/function/from.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::{
1111
path::PathBuf,
1212
};
1313

14-
use super::script_function::DynamicScriptFunctionMut;
14+
use super::script_function::{DynamicScriptFunction, DynamicScriptFunctionMut};
1515

1616
/// Describes the procedure for constructing a value of type `T` from a [`ScriptValue`].
1717
///
@@ -393,6 +393,23 @@ where
393393
impl FromScript for DynamicScriptFunctionMut {
394394
type This<'w> = Self;
395395

396+
fn from_script(value: ScriptValue, _: WorldGuard<'_>) -> Result<Self::This<'_>, InteropError>
397+
where
398+
Self: Sized,
399+
{
400+
match value {
401+
ScriptValue::FunctionMut(f) => Ok(f),
402+
_ => Err(InteropError::value_mismatch(
403+
std::any::TypeId::of::<Self>(),
404+
value,
405+
)),
406+
}
407+
}
408+
}
409+
410+
impl FromScript for DynamicScriptFunction {
411+
type This<'w> = Self;
412+
396413
fn from_script(value: ScriptValue, _: WorldGuard<'_>) -> Result<Self::This<'_>, InteropError>
397414
where
398415
Self: Sized,

crates/bevy_mod_scripting_core/src/bindings/function/into.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ impl IntoScript for () {
3333
self_type_dependency_only!(());
3434

3535
impl IntoScript for DynamicScriptFunctionMut {
36+
fn into_script(self, _world: WorldGuard) -> Result<ScriptValue, InteropError> {
37+
Ok(ScriptValue::FunctionMut(self))
38+
}
39+
}
40+
41+
impl IntoScript for DynamicScriptFunction {
3642
fn into_script(self, _world: WorldGuard) -> Result<ScriptValue, InteropError> {
3743
Ok(ScriptValue::Function(self))
3844
}

crates/bevy_mod_scripting_core/src/bindings/function/mod.rs

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,3 @@ pub mod into;
44
pub mod into_ref;
55
pub mod namespace;
66
pub mod script_function;
7-
8-
use script_function::{CallerContext, DynamicScriptFunction, DynamicScriptFunctionMut};
9-
10-
use crate::error::InteropError;
11-
12-
use super::{script_value::ScriptValue, WorldCallbackAccess, WorldGuard};
13-
14-
/// Can be implemented for callables which require dynamic access to the world to be called.
15-
///
16-
/// The claim and release functions must be used to scope the access to the world such that function output .
17-
pub trait CallScriptFunction {
18-
fn call_script_function<I: IntoIterator<Item = ScriptValue>>(
19-
&mut self,
20-
args: I,
21-
world: WorldGuard,
22-
context: CallerContext,
23-
) -> Result<ScriptValue, InteropError>;
24-
}
25-
26-
impl CallScriptFunction for DynamicScriptFunction {
27-
fn call_script_function<I: IntoIterator<Item = ScriptValue>>(
28-
&mut self,
29-
args: I,
30-
world: WorldGuard,
31-
context: CallerContext,
32-
) -> Result<ScriptValue, InteropError> {
33-
let args = args.into_iter().collect::<Vec<_>>();
34-
let world_callback_access = WorldCallbackAccess::from_guard(world.clone());
35-
// should we be inlining call errors into the return value?
36-
let return_val = self.call(context, world_callback_access, args);
37-
match return_val {
38-
ScriptValue::Error(e) => Err(InteropError::function_interop_error(
39-
self.name(),
40-
context.self_type,
41-
e,
42-
)),
43-
v => Ok(v),
44-
}
45-
}
46-
}
47-
48-
impl CallScriptFunction for DynamicScriptFunctionMut {
49-
fn call_script_function<I: IntoIterator<Item = ScriptValue>>(
50-
&mut self,
51-
args: I,
52-
world: WorldGuard,
53-
context: CallerContext,
54-
) -> Result<ScriptValue, InteropError> {
55-
let args = args.into_iter().collect::<Vec<_>>();
56-
let world_callback_access = WorldCallbackAccess::from_guard(world.clone());
57-
// should we be inlining call errors into the return value?
58-
let return_val = self.call(context, world_callback_access, args);
59-
match return_val {
60-
ScriptValue::Error(e) => Err(InteropError::function_interop_error(
61-
self.name(),
62-
context.self_type,
63-
e,
64-
)),
65-
v => Ok(v),
66-
}
67-
}
68-
}

crates/bevy_mod_scripting_core/src/bindings/function/namespace.rs

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::bindings::function::script_function::{
22
AppScriptFunctionRegistry, DynamicScriptFunction, GetFunctionTypeDependencies, ScriptFunction,
3-
ScriptFunctionRegistry,
43
};
54
use bevy::{
65
prelude::{AppTypeRegistry, World},
@@ -53,10 +52,14 @@ pub trait GetNamespacedFunction {
5352
}
5453
}
5554

55+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
5656
pub enum Namespace {
57-
/// The function is registered in the global namespace, i.e. with no namespace
57+
/// The function is registered in the global namespace, i.e. with no namespace.
58+
/// In practice functions in this namespace should be callable directly by their name, i.e. `my_function()`
59+
#[default]
5860
Global,
59-
/// The function is registered in the namespace corresponding to the given type
61+
/// The function is registered in the namespace corresponding to the given type.
62+
/// In practice functions in this namespace should be callable by their qualified name, i.e. `MyType.my_function()`
6063
OnType(TypeId),
6164
}
6265

@@ -79,63 +82,61 @@ impl Namespace {
7982
}
8083

8184
/// Returns the fully qualified name of a function in this namespace
82-
pub fn function_name(self, name: Cow<'static, str>) -> Cow<'static, str> {
85+
pub fn function_name<I: Into<Cow<'static, str>>>(self, name: I) -> Cow<'static, str> {
8386
match self {
84-
Namespace::Global => name,
85-
Namespace::OnType(type_id) => Cow::Owned(format!("{:?}::{}", type_id, name)),
87+
Namespace::Global => name.into(),
88+
Namespace::OnType(type_id) => Cow::Owned(format!("{:?}::{}", type_id, name.into())),
8689
}
8790
}
8891
}
8992

90-
impl RegisterNamespacedFunction for ScriptFunctionRegistry {
91-
fn register_namespaced_function<S, N, F, M>(&mut self, name: N, function: F)
92-
where
93-
N: Into<Cow<'static, str>>,
94-
S: IntoNamespace,
95-
F: ScriptFunction<'static, M>,
96-
{
97-
let cow: Cow<'static, str> = name.into();
98-
let function_name = S::into_namespace().function_name(cow);
99-
self.register(function_name, function);
100-
}
101-
}
102-
103-
impl GetNamespacedFunction for ScriptFunctionRegistry {
104-
fn iter_overloads_namespaced<N>(
105-
&self,
106-
name: N,
107-
namespace: Namespace,
108-
) -> impl Iterator<Item = &DynamicScriptFunction>
109-
where
110-
N: Into<Cow<'static, str>>,
111-
{
112-
let cow: Cow<'static, str> = name.into();
113-
let function_name = namespace.function_name(cow);
114-
self.iter_overloads(function_name)
115-
}
116-
117-
fn get_namespaced_function<N>(
118-
&self,
119-
name: N,
120-
namespace: Namespace,
121-
) -> Option<&DynamicScriptFunction>
122-
where
123-
N: Into<Cow<'static, str>>,
124-
{
125-
let cow: Cow<'static, str> = name.into();
126-
let function_name = namespace.function_name(cow);
127-
self.get_first(&function_name)
128-
}
129-
130-
fn has_namespaced_function<N>(&self, name: N, namespace: Namespace) -> bool
131-
where
132-
N: Into<Cow<'static, str>>,
133-
{
134-
let cow: Cow<'static, str> = name.into();
135-
let function_name = namespace.function_name(cow);
136-
self.contains(&function_name)
137-
}
138-
}
93+
// impl RegisterNamespacedFunction for ScriptFunctionRegistry {
94+
// fn register_namespaced_function<S, N, F, M>(&mut self, name: N, function: F)
95+
// where
96+
// N: Into<Cow<'static, str>>,
97+
// S: IntoNamespace,
98+
// F: ScriptFunction<'static, M>,
99+
// {
100+
// self.register(S::into_namespace(), name, function);
101+
// }
102+
// }
103+
104+
// impl GetNamespacedFunction for ScriptFunctionRegistry {
105+
// fn iter_overloads_namespaced<N>(
106+
// &self,
107+
// name: N,
108+
// namespace: Namespace,
109+
// ) -> impl Iterator<Item = &DynamicScriptFunction>
110+
// where
111+
// N: Into<Cow<'static, str>>,
112+
// {
113+
// let cow: Cow<'static, str> = name.into();
114+
// let function_name = namespace.function_name(cow);
115+
// self.iter_overloads(function_name)
116+
// }
117+
118+
// fn get_namespaced_function<N>(
119+
// &self,
120+
// name: N,
121+
// namespace: Namespace,
122+
// ) -> Option<&DynamicScriptFunction>
123+
// where
124+
// N: Into<Cow<'static, str>>,
125+
// {
126+
// let cow: Cow<'static, str> = name.into();
127+
// let function_name = namespace.function_name(cow);
128+
// self.get_first(&function_name)
129+
// }
130+
131+
// fn has_namespaced_function<N>(&self, name: N, namespace: Namespace) -> bool
132+
// where
133+
// N: Into<Cow<'static, str>>,
134+
// {
135+
// let cow: Cow<'static, str> = name.into();
136+
// let function_name = namespace.function_name(cow);
137+
// self.contains(&function_name)
138+
// }
139+
// }
139140

140141
pub struct NamespaceBuilder<'a, N> {
141142
namespace: PhantomData<N>,
@@ -179,7 +180,7 @@ impl<'a, S: IntoNamespace> NamespaceBuilder<'a, S> {
179180
.world
180181
.get_resource_or_init::<AppScriptFunctionRegistry>();
181182
let mut registry = registry.write();
182-
registry.register_namespaced_function::<S, _, F, M>(name, function);
183+
registry.register(S::into_namespace(), name, function);
183184
}
184185
{
185186
let type_registry = self.world.get_resource_or_init::<AppTypeRegistry>();

0 commit comments

Comments
 (0)