Skip to content

Commit 7e2e970

Browse files
authored
refactor: refactor ReflectReference internally (#406)
# Summary Cleans the code up a bit, moves reflect base constructors into that type, and guarantees that typeid always corresponds to a valid reflect type
1 parent 87c6734 commit 7e2e970

File tree

2 files changed

+72
-31
lines changed

2 files changed

+72
-31
lines changed

crates/bevy_mod_scripting_core/src/bindings/pretty_print.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ impl ReflectReferencePrinter {
123123
}
124124

125125
fn pretty_print_base(base: &ReflectBaseType, world: Option<WorldGuard>, out: &mut String) {
126-
let type_id = base.type_id;
126+
let type_id = base.type_id();
127127
let type_path = if let Some(world) = world {
128128
type_id.display_with_world(world.clone())
129129
} else {

crates/bevy_mod_scripting_core/src/bindings/reference.rs

+71-30
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use std::{any::TypeId, fmt::Debug};
3333
/// Bindings defined on this type, apply to ALL references.
3434
#[derive(Debug, Clone, PartialEq, Eq, Reflect)]
3535
#[reflect(Default, opaque)]
36+
#[non_exhaustive]
3637
pub struct ReflectReference {
3738
/// The base type and id of the value we want to access
3839
pub base: ReflectBaseType,
@@ -124,45 +125,27 @@ impl ReflectReference {
124125
value: Box<dyn PartialReflect>,
125126
allocator: &mut ReflectAllocator,
126127
) -> Result<ReflectReference, InteropError> {
127-
match value.get_represented_type_info() {
128-
Some(i) => {
129-
let id = allocator.allocate_boxed(value);
130-
Ok(ReflectReference {
131-
base: ReflectBaseType {
132-
type_id: i.type_id(),
133-
base_id: ReflectBase::Owned(id),
134-
},
135-
reflect_path: ParsedPath(Vec::default()),
136-
})
137-
}
138-
None => Err(InteropError::unsupported_operation(None, Some(value), "Tried to create a reference to a partial reflect value with no represented type info")),
139-
}
128+
Ok(ReflectReference {
129+
base: ReflectBaseType::new_allocated_base_partial(value, allocator)?,
130+
reflect_path: ParsedPath(Vec::default()),
131+
})
140132
}
141133

142134
/// Create a new reference to a value by allocating it.
143135
pub fn new_allocated_boxed(
144136
value: Box<dyn Reflect>,
145137
allocator: &mut ReflectAllocator,
146138
) -> ReflectReference {
147-
let type_id = value.type_id();
148-
let id = allocator.allocate_boxed(value.into_partial_reflect());
149139
ReflectReference {
150-
base: ReflectBaseType {
151-
type_id,
152-
base_id: ReflectBase::Owned(id),
153-
},
140+
base: ReflectBaseType::new_allocated_base(value, allocator),
154141
reflect_path: ParsedPath(Vec::default()),
155142
}
156143
}
157144

158145
/// Create a new reference to resource
159146
pub fn new_resource_ref<T: Resource>(world: WorldGuard) -> Result<Self, InteropError> {
160-
let reflect_id = ReflectAccessId::for_resource::<T>(&world.as_unsafe_world_cell()?)?;
161147
Ok(Self {
162-
base: ReflectBaseType {
163-
type_id: TypeId::of::<T>(),
164-
base_id: ReflectBase::Resource(reflect_id.into()),
165-
},
148+
base: ReflectBaseType::new_resource_base::<T>(world)?,
166149
reflect_path: ParsedPath(Vec::default()),
167150
})
168151
}
@@ -172,12 +155,8 @@ impl ReflectReference {
172155
entity: Entity,
173156
world: WorldGuard,
174157
) -> Result<Self, InteropError> {
175-
let reflect_id = ReflectAccessId::for_component::<T>(&world.as_unsafe_world_cell()?)?;
176158
Ok(Self {
177-
base: ReflectBaseType {
178-
type_id: TypeId::of::<T>(),
179-
base_id: ReflectBase::Component(entity, reflect_id.into()),
180-
},
159+
base: ReflectBaseType::new_component_base::<T>(entity, world)?,
181160
reflect_path: ParsedPath(Vec::default()),
182161
})
183162
}
@@ -407,6 +386,7 @@ impl ReflectReference {
407386
self.base.type_id,
408387
"Invariant violated"
409388
);
389+
410390
let base = unsafe { from_ptr_data.as_reflect_mut(ptr.into_inner()) };
411391
drop(type_registry);
412392
self.walk_path_mut(base.as_partial_reflect_mut())
@@ -435,11 +415,72 @@ impl ReflectReference {
435415
/// The type id and base id of the value we want to access
436416
pub struct ReflectBaseType {
437417
/// The type id of the value we want to access
438-
pub type_id: TypeId,
418+
/// This MUST always be inline with the type id we are pointing to
419+
pub(crate) type_id: TypeId,
439420
/// The base kind of the value we want to access
440421
pub base_id: ReflectBase,
441422
}
442423

424+
impl ReflectBaseType {
425+
#[inline]
426+
/// Returns the type id of the value pointed to by the base
427+
pub fn type_id(&self) -> TypeId {
428+
self.type_id
429+
}
430+
431+
/// Create a new reflection base pointing to a component on the given entity
432+
pub fn new_component_base<T: Component>(
433+
entity: Entity,
434+
world: WorldGuard,
435+
) -> Result<Self, InteropError> {
436+
let reflect_id = ReflectAccessId::for_component::<T>(&world.as_unsafe_world_cell()?)?;
437+
Ok(Self {
438+
type_id: TypeId::of::<T>(),
439+
base_id: ReflectBase::Component(entity, reflect_id.into()),
440+
})
441+
}
442+
443+
/// Create a new reflection base pointing to a resource
444+
pub fn new_resource_base<T: Resource>(world: WorldGuard) -> Result<Self, InteropError> {
445+
let reflect_id = ReflectAccessId::for_resource::<T>(&world.as_unsafe_world_cell()?)?;
446+
Ok(Self {
447+
type_id: TypeId::of::<T>(),
448+
base_id: ReflectBase::Resource(reflect_id.into()),
449+
})
450+
}
451+
452+
/// Create a new reflection base pointing to a value which will be allocated in the allocator
453+
pub fn new_allocated_base(value: Box<dyn Reflect>, allocator: &mut ReflectAllocator) -> Self {
454+
let type_id = value.type_id();
455+
let id = allocator.allocate_boxed(value.into_partial_reflect());
456+
Self {
457+
type_id,
458+
base_id: ReflectBase::Owned(id),
459+
}
460+
}
461+
462+
/// Create a new reflection base pointing to a value which will be allocated in the allocator
463+
pub fn new_allocated_base_partial(
464+
value: Box<dyn PartialReflect>,
465+
allocator: &mut ReflectAllocator,
466+
) -> Result<Self, InteropError> {
467+
match value.get_represented_type_info() {
468+
Some(i) => {
469+
let id = allocator.allocate_boxed(value);
470+
Ok(Self {
471+
type_id: i.type_id(),
472+
base_id: ReflectBase::Owned(id),
473+
})
474+
}
475+
None => Err(InteropError::unsupported_operation(
476+
None,
477+
Some(value),
478+
"Tried to create a reference base to a partial reflect value with no represented type info",
479+
)),
480+
}
481+
}
482+
}
483+
443484
/// The Id of the kind of reflection base being pointed to
444485
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
445486
pub enum ReflectBase {

0 commit comments

Comments
 (0)