Skip to main content

bevy_reflect/impls/
smallvec.rs

1use crate::{
2    list::{List, ListInfo, ListIter},
3    utility::GenericTypeInfoCell,
4    ApplyError, FromReflect, FromType, Generics, GetTypeRegistration, MaybeTyped, PartialReflect,
5    Reflect, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
6    TypeParamInfo, TypePath, TypeRegistration, Typed,
7};
8use alloc::{boxed::Box, vec::Vec};
9use bevy_reflect::ReflectCloneError;
10use bevy_reflect_derive::impl_type_path;
11use core::any::Any;
12use smallvec::{Array as SmallArray, SmallVec};
13
14impl<T: SmallArray + TypePath + Send + Sync> List for SmallVec<T>
15where
16    T::Item: FromReflect + MaybeTyped + TypePath,
17{
18    fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
19        if index < SmallVec::len(self) {
20            Some(&self[index] as &dyn PartialReflect)
21        } else {
22            None
23        }
24    }
25
26    fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
27        if index < SmallVec::len(self) {
28            Some(&mut self[index] as &mut dyn PartialReflect)
29        } else {
30            None
31        }
32    }
33
34    fn insert(&mut self, index: usize, value: Box<dyn PartialReflect>) {
35        let value = value.try_take::<T::Item>().unwrap_or_else(|value| {
36            <T as SmallArray>::Item::from_reflect(&*value).unwrap_or_else(|| {
37                panic!(
38                    "Attempted to insert invalid value of type {}.",
39                    value.reflect_type_path()
40                )
41            })
42        });
43        SmallVec::insert(self, index, value);
44    }
45
46    fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
47        Box::new(self.remove(index))
48    }
49
50    fn push(&mut self, value: Box<dyn PartialReflect>) {
51        let value = value.try_take::<T::Item>().unwrap_or_else(|value| {
52            <T as SmallArray>::Item::from_reflect(&*value).unwrap_or_else(|| {
53                panic!(
54                    "Attempted to push invalid value of type {}.",
55                    value.reflect_type_path()
56                )
57            })
58        });
59        SmallVec::push(self, value);
60    }
61
62    fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
63        self.pop()
64            .map(|value| Box::new(value) as Box<dyn PartialReflect>)
65    }
66
67    fn len(&self) -> usize {
68        <SmallVec<T>>::len(self)
69    }
70
71    fn iter(&self) -> ListIter<'_> {
72        ListIter::new(self)
73    }
74
75    fn drain(&mut self) -> Vec<Box<dyn PartialReflect>> {
76        self.drain(..)
77            .map(|value| Box::new(value) as Box<dyn PartialReflect>)
78            .collect()
79    }
80}
81
82impl<T: SmallArray + TypePath + Send + Sync> PartialReflect for SmallVec<T>
83where
84    T::Item: FromReflect + MaybeTyped + TypePath,
85{
86    fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
87        Some(<Self as Typed>::type_info())
88    }
89
90    #[inline]
91    fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
92        self
93    }
94
95    fn as_partial_reflect(&self) -> &dyn PartialReflect {
96        self
97    }
98
99    fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
100        self
101    }
102
103    fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
104        Ok(self)
105    }
106
107    fn try_as_reflect(&self) -> Option<&dyn Reflect> {
108        Some(self)
109    }
110
111    fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
112        Some(self)
113    }
114
115    fn apply(&mut self, value: &dyn PartialReflect) {
116        crate::list::list_apply(self, value);
117    }
118
119    fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
120        crate::list::list_try_apply(self, value)
121    }
122
123    fn reflect_kind(&self) -> ReflectKind {
124        ReflectKind::List
125    }
126
127    fn reflect_ref(&self) -> ReflectRef<'_> {
128        ReflectRef::List(self)
129    }
130
131    fn reflect_mut(&mut self) -> ReflectMut<'_> {
132        ReflectMut::List(self)
133    }
134
135    fn reflect_owned(self: Box<Self>) -> ReflectOwned {
136        ReflectOwned::List(self)
137    }
138
139    fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
140        Ok(Box::new(
141            // `(**self)` avoids getting `SmallVec<T> as List::iter`, which
142            // would give us the wrong item type.
143            (**self)
144                .iter()
145                .map(PartialReflect::reflect_clone_and_take)
146                .collect::<Result<Self, ReflectCloneError>>()?,
147        ))
148    }
149
150    fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
151        crate::list::list_partial_eq(self, value)
152    }
153
154    fn reflect_partial_cmp(&self, value: &dyn PartialReflect) -> Option<core::cmp::Ordering> {
155        crate::list::list_partial_cmp(self, value)
156    }
157}
158
159impl<T: SmallArray + TypePath + Send + Sync> Reflect for SmallVec<T>
160where
161    T::Item: FromReflect + MaybeTyped + TypePath,
162{
163    fn into_any(self: Box<Self>) -> Box<dyn Any> {
164        self
165    }
166
167    fn as_any(&self) -> &dyn Any {
168        self
169    }
170
171    fn as_any_mut(&mut self) -> &mut dyn Any {
172        self
173    }
174
175    fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
176        self
177    }
178
179    fn as_reflect(&self) -> &dyn Reflect {
180        self
181    }
182
183    fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
184        self
185    }
186
187    fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
188        *self = value.take()?;
189        Ok(())
190    }
191}
192
193impl<T: SmallArray + TypePath + Send + Sync + 'static> Typed for SmallVec<T>
194where
195    T::Item: FromReflect + MaybeTyped + TypePath,
196{
197    fn type_info() -> &'static TypeInfo {
198        static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
199        CELL.get_or_insert::<Self, _>(|| {
200            TypeInfo::List(
201                ListInfo::new::<Self, T::Item>()
202                    .with_generics(Generics::from_iter([TypeParamInfo::new::<T>("T")])),
203            )
204        })
205    }
206}
207
208impl_type_path!(::smallvec::SmallVec<T: SmallArray>);
209
210impl<T: SmallArray + TypePath + Send + Sync> FromReflect for SmallVec<T>
211where
212    T::Item: FromReflect + MaybeTyped + TypePath,
213{
214    fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
215        let ref_list = reflect.reflect_ref().as_list().ok()?;
216
217        let mut new_list = Self::with_capacity(ref_list.len());
218
219        for field in ref_list.iter() {
220            new_list.push(<T as SmallArray>::Item::from_reflect(field)?);
221        }
222
223        Some(new_list)
224    }
225}
226
227impl<T: SmallArray + TypePath + Send + Sync> GetTypeRegistration for SmallVec<T>
228where
229    T::Item: FromReflect + MaybeTyped + TypePath,
230{
231    fn get_type_registration() -> TypeRegistration {
232        let mut registration = TypeRegistration::of::<SmallVec<T>>();
233        registration.insert::<ReflectFromPtr>(FromType::<SmallVec<T>>::from_type());
234        registration
235    }
236}
237
238#[cfg(feature = "functions")]
239crate::func::macros::impl_function_traits!(SmallVec<T>; <T: SmallArray + TypePath + Send + Sync> where T::Item: FromReflect + MaybeTyped + TypePath);