Skip to content

Commit 1674938

Browse files
authored
bevy_reflect: Split up the std module (#18939)
> [!important] > To **maintainers**: we should wait to merge this one in until after #18944 lands so that cherry-picking the latter for 0.16.1 is simpler. # Objective The `std` module is where we implement the reflection traits for types that are exported from `std` (including `core` and `alloc`). Over time, this file has grown increasingly large, making it difficult to navigate and a pain point for merge conflicts. The goal of this PR is to break up the module into smaller chunks. ## Solution The `std` module has been split into many submodules: - `alloc` - `bevy_platform` - `core` - `std` Each of these new modules is comprised of submodules that closely resemble the actual module. For example, the impls for `::alloc::vec::Vec` have been moved to `bevy_reflect::impls::alloc::vec::Vec`. Some liberties were taken. For example, `Cow<'static, Path>` was kept in `bevy_reflect::impls::std::path` rather than `bevy_reflect::impls::alloc::borrow`. You may ask: _Isn't this a little overkill? Why does the one-line impl for `TypeId` need its own file?_ And yes, it is partly overkill. But the benefit with this approach is that where an `std`-related type should live is mostly unambiguous. If we wanted to reflect `::core::net::Ipv4Addr`, it's very clear that it should be done in `bevy_reflect::impls::core::net`. We can discuss better ways of breaking this up if people have other ideas or opinions, but I think this is a pretty straightforward way of doing it. ### Note to Reviewers The code is pretty much copy-paste from the mega module to the new submodules. It's probably best to focus efforts on reviewing the general module structure, as well as maybe which impls are included where. You _can_ review the code contained within each impl, but I promise you the only thing I touched were the paths in the macros so they could be more hygienic :) ## Testing You can just check that everything compiles still: ``` cargo check -p bevy_reflect --tests ```
1 parent 85284cb commit 1674938

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+3191
-2878
lines changed

crates/bevy_reflect/src/func/return_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ macro_rules! impl_into_return {
129129
)?
130130
{
131131
fn into_return<'into_return>(self) -> $crate::func::Return<'into_return> where Self: 'into_return {
132-
$crate::func::Return::Owned(Box::new(self))
132+
$crate::func::Return::Owned(bevy_platform::prelude::Box::new(self))
133133
}
134134
}
135135

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
use crate::{
2+
error::ReflectCloneError,
3+
kind::{ReflectKind, ReflectMut, ReflectOwned, ReflectRef},
4+
list::{List, ListInfo, ListIter},
5+
prelude::*,
6+
reflect::{impl_full_reflect, ApplyError},
7+
type_info::{MaybeTyped, OpaqueInfo, TypeInfo, Typed},
8+
type_registry::{
9+
FromType, GetTypeRegistration, ReflectDeserialize, ReflectFromPtr, ReflectSerialize,
10+
TypeRegistration, TypeRegistry,
11+
},
12+
utility::{reflect_hasher, GenericTypeInfoCell, NonGenericTypeInfoCell},
13+
};
14+
use alloc::borrow::Cow;
15+
use alloc::vec::Vec;
16+
use bevy_platform::prelude::*;
17+
use bevy_reflect_derive::impl_type_path;
18+
use core::any::Any;
19+
use core::fmt;
20+
use core::hash::{Hash, Hasher};
21+
22+
impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: ToOwned + ?Sized>);
23+
24+
impl PartialReflect for Cow<'static, str> {
25+
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
26+
Some(<Self as Typed>::type_info())
27+
}
28+
29+
#[inline]
30+
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
31+
self
32+
}
33+
34+
fn as_partial_reflect(&self) -> &dyn PartialReflect {
35+
self
36+
}
37+
38+
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
39+
self
40+
}
41+
42+
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
43+
Ok(self)
44+
}
45+
46+
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
47+
Some(self)
48+
}
49+
50+
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
51+
Some(self)
52+
}
53+
54+
fn reflect_kind(&self) -> ReflectKind {
55+
ReflectKind::Opaque
56+
}
57+
58+
fn reflect_ref(&self) -> ReflectRef {
59+
ReflectRef::Opaque(self)
60+
}
61+
62+
fn reflect_mut(&mut self) -> ReflectMut {
63+
ReflectMut::Opaque(self)
64+
}
65+
66+
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
67+
ReflectOwned::Opaque(self)
68+
}
69+
70+
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
71+
Ok(Box::new(self.clone()))
72+
}
73+
74+
fn reflect_hash(&self) -> Option<u64> {
75+
let mut hasher = reflect_hasher();
76+
Hash::hash(&Any::type_id(self), &mut hasher);
77+
Hash::hash(self, &mut hasher);
78+
Some(hasher.finish())
79+
}
80+
81+
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
82+
if let Some(value) = value.try_downcast_ref::<Self>() {
83+
Some(PartialEq::eq(self, value))
84+
} else {
85+
Some(false)
86+
}
87+
}
88+
89+
fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90+
fmt::Debug::fmt(self, f)
91+
}
92+
93+
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
94+
if let Some(value) = value.try_downcast_ref::<Self>() {
95+
self.clone_from(value);
96+
} else {
97+
return Err(ApplyError::MismatchedTypes {
98+
from_type: value.reflect_type_path().into(),
99+
// If we invoke the reflect_type_path on self directly the borrow checker complains that the lifetime of self must outlive 'static
100+
to_type: Self::type_path().into(),
101+
});
102+
}
103+
Ok(())
104+
}
105+
}
106+
107+
impl_full_reflect!(for Cow<'static, str>);
108+
109+
impl Typed for Cow<'static, str> {
110+
fn type_info() -> &'static TypeInfo {
111+
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
112+
CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::<Self>()))
113+
}
114+
}
115+
116+
impl GetTypeRegistration for Cow<'static, str> {
117+
fn get_type_registration() -> TypeRegistration {
118+
let mut registration = TypeRegistration::of::<Cow<'static, str>>();
119+
registration.insert::<ReflectDeserialize>(FromType::<Cow<'static, str>>::from_type());
120+
registration.insert::<ReflectFromPtr>(FromType::<Cow<'static, str>>::from_type());
121+
registration.insert::<ReflectFromReflect>(FromType::<Cow<'static, str>>::from_type());
122+
registration.insert::<ReflectSerialize>(FromType::<Cow<'static, str>>::from_type());
123+
registration
124+
}
125+
}
126+
127+
impl FromReflect for Cow<'static, str> {
128+
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
129+
Some(reflect.try_downcast_ref::<Cow<'static, str>>()?.clone())
130+
}
131+
}
132+
133+
#[cfg(feature = "functions")]
134+
crate::func::macros::impl_function_traits!(Cow<'static, str>);
135+
136+
impl<T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration> List
137+
for Cow<'static, [T]>
138+
{
139+
fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
140+
self.as_ref().get(index).map(|x| x as &dyn PartialReflect)
141+
}
142+
143+
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
144+
self.to_mut()
145+
.get_mut(index)
146+
.map(|x| x as &mut dyn PartialReflect)
147+
}
148+
149+
fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>) {
150+
let value = T::take_from_reflect(element).unwrap_or_else(|value| {
151+
panic!(
152+
"Attempted to insert invalid value of type {}.",
153+
value.reflect_type_path()
154+
);
155+
});
156+
self.to_mut().insert(index, value);
157+
}
158+
159+
fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
160+
Box::new(self.to_mut().remove(index))
161+
}
162+
163+
fn push(&mut self, value: Box<dyn PartialReflect>) {
164+
let value = T::take_from_reflect(value).unwrap_or_else(|value| {
165+
panic!(
166+
"Attempted to push invalid value of type {}.",
167+
value.reflect_type_path()
168+
)
169+
});
170+
self.to_mut().push(value);
171+
}
172+
173+
fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
174+
self.to_mut()
175+
.pop()
176+
.map(|value| Box::new(value) as Box<dyn PartialReflect>)
177+
}
178+
179+
fn len(&self) -> usize {
180+
self.as_ref().len()
181+
}
182+
183+
fn iter(&self) -> ListIter {
184+
ListIter::new(self)
185+
}
186+
187+
fn drain(&mut self) -> Vec<Box<dyn PartialReflect>> {
188+
self.to_mut()
189+
.drain(..)
190+
.map(|value| Box::new(value) as Box<dyn PartialReflect>)
191+
.collect()
192+
}
193+
}
194+
195+
impl<T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration> PartialReflect
196+
for Cow<'static, [T]>
197+
{
198+
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
199+
Some(<Self as Typed>::type_info())
200+
}
201+
202+
#[inline]
203+
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
204+
self
205+
}
206+
207+
fn as_partial_reflect(&self) -> &dyn PartialReflect {
208+
self
209+
}
210+
211+
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
212+
self
213+
}
214+
215+
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
216+
Ok(self)
217+
}
218+
219+
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
220+
Some(self)
221+
}
222+
223+
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
224+
Some(self)
225+
}
226+
227+
fn reflect_kind(&self) -> ReflectKind {
228+
ReflectKind::List
229+
}
230+
231+
fn reflect_ref(&self) -> ReflectRef {
232+
ReflectRef::List(self)
233+
}
234+
235+
fn reflect_mut(&mut self) -> ReflectMut {
236+
ReflectMut::List(self)
237+
}
238+
239+
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
240+
ReflectOwned::List(self)
241+
}
242+
243+
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
244+
Ok(Box::new(self.clone()))
245+
}
246+
247+
fn reflect_hash(&self) -> Option<u64> {
248+
crate::list_hash(self)
249+
}
250+
251+
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
252+
crate::list_partial_eq(self, value)
253+
}
254+
255+
fn apply(&mut self, value: &dyn PartialReflect) {
256+
crate::list_apply(self, value);
257+
}
258+
259+
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
260+
crate::list_try_apply(self, value)
261+
}
262+
}
263+
264+
impl_full_reflect!(
265+
<T> for Cow<'static, [T]>
266+
where
267+
T: FromReflect + Clone + MaybeTyped + TypePath + GetTypeRegistration,
268+
);
269+
270+
impl<T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration> Typed
271+
for Cow<'static, [T]>
272+
{
273+
fn type_info() -> &'static TypeInfo {
274+
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
275+
CELL.get_or_insert::<Self, _>(|| TypeInfo::List(ListInfo::new::<Self, T>()))
276+
}
277+
}
278+
279+
impl<T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration> GetTypeRegistration
280+
for Cow<'static, [T]>
281+
{
282+
fn get_type_registration() -> TypeRegistration {
283+
TypeRegistration::of::<Cow<'static, [T]>>()
284+
}
285+
286+
fn register_type_dependencies(registry: &mut TypeRegistry) {
287+
registry.register::<T>();
288+
}
289+
}
290+
291+
impl<T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration> FromReflect
292+
for Cow<'static, [T]>
293+
{
294+
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
295+
let ref_list = reflect.reflect_ref().as_list().ok()?;
296+
297+
let mut temp_vec = Vec::with_capacity(ref_list.len());
298+
299+
for field in ref_list.iter() {
300+
temp_vec.push(T::from_reflect(field)?);
301+
}
302+
303+
Some(temp_vec.into())
304+
}
305+
}
306+
307+
#[cfg(feature = "functions")]
308+
crate::func::macros::impl_function_traits!(Cow<'static, [T]>; <T: FromReflect + MaybeTyped + Clone + TypePath + GetTypeRegistration>);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use bevy_reflect_derive::impl_reflect_opaque;
2+
3+
impl_reflect_opaque!(::alloc::collections::BinaryHeap<T: Clone>(Clone));
4+
5+
#[cfg(test)]
6+
mod tests {
7+
use alloc::collections::BTreeMap;
8+
use bevy_reflect::Reflect;
9+
10+
#[test]
11+
fn should_partial_eq_btree_map() {
12+
let mut a = BTreeMap::new();
13+
a.insert(0usize, 1.23_f64);
14+
let b = a.clone();
15+
let mut c = BTreeMap::new();
16+
c.insert(0usize, 3.21_f64);
17+
18+
let a: &dyn Reflect = &a;
19+
let b: &dyn Reflect = &b;
20+
let c: &dyn Reflect = &c;
21+
assert!(a
22+
.reflect_partial_eq(b.as_partial_reflect())
23+
.unwrap_or_default());
24+
assert!(!a
25+
.reflect_partial_eq(c.as_partial_reflect())
26+
.unwrap_or_default());
27+
}
28+
}

0 commit comments

Comments
 (0)