1use bevy_reflect_derive::impl_type_path;
2
3use crate::{
4 self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, ApplyError, DynamicStruct,
5 DynamicTuple, Enum, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple,
6 TypeInfo, VariantFieldIter, VariantType,
7};
8use std::any::Any;
9use std::fmt::Formatter;
10
11#[derive(Debug, Default)]
13pub enum DynamicVariant {
14 #[default]
15 Unit,
16 Tuple(DynamicTuple),
17 Struct(DynamicStruct),
18}
19
20impl Clone for DynamicVariant {
21 fn clone(&self) -> Self {
22 match self {
23 DynamicVariant::Unit => DynamicVariant::Unit,
24 DynamicVariant::Tuple(data) => DynamicVariant::Tuple(data.clone_dynamic()),
25 DynamicVariant::Struct(data) => DynamicVariant::Struct(data.clone_dynamic()),
26 }
27 }
28}
29
30impl From<DynamicTuple> for DynamicVariant {
31 fn from(dyn_tuple: DynamicTuple) -> Self {
32 Self::Tuple(dyn_tuple)
33 }
34}
35
36impl From<DynamicStruct> for DynamicVariant {
37 fn from(dyn_struct: DynamicStruct) -> Self {
38 Self::Struct(dyn_struct)
39 }
40}
41
42impl From<()> for DynamicVariant {
43 fn from(_: ()) -> Self {
44 Self::Unit
45 }
46}
47
48#[derive(Default, Debug)]
73pub struct DynamicEnum {
74 represented_type: Option<&'static TypeInfo>,
75 variant_name: String,
76 variant_index: usize,
77 variant: DynamicVariant,
78}
79
80impl DynamicEnum {
81 pub fn new<I: Into<String>, V: Into<DynamicVariant>>(variant_name: I, variant: V) -> Self {
89 Self {
90 represented_type: None,
91 variant_index: 0,
92 variant_name: variant_name.into(),
93 variant: variant.into(),
94 }
95 }
96
97 pub fn new_with_index<I: Into<String>, V: Into<DynamicVariant>>(
106 variant_index: usize,
107 variant_name: I,
108 variant: V,
109 ) -> Self {
110 Self {
111 represented_type: None,
112 variant_index,
113 variant_name: variant_name.into(),
114 variant: variant.into(),
115 }
116 }
117
118 pub fn set_represented_type(&mut self, represented_type: Option<&'static TypeInfo>) {
126 if let Some(represented_type) = represented_type {
127 assert!(
128 matches!(represented_type, TypeInfo::Enum(_)),
129 "expected TypeInfo::Enum but received: {:?}",
130 represented_type
131 );
132 }
133
134 self.represented_type = represented_type;
135 }
136
137 pub fn set_variant<I: Into<String>, V: Into<DynamicVariant>>(&mut self, name: I, variant: V) {
139 self.variant_name = name.into();
140 self.variant = variant.into();
141 }
142
143 pub fn set_variant_with_index<I: Into<String>, V: Into<DynamicVariant>>(
145 &mut self,
146 variant_index: usize,
147 variant_name: I,
148 variant: V,
149 ) {
150 self.variant_index = variant_index;
151 self.variant_name = variant_name.into();
152 self.variant = variant.into();
153 }
154
155 pub fn from<TEnum: Enum>(value: TEnum) -> Self {
159 Self::from_ref(&value)
160 }
161
162 pub fn from_ref<TEnum: Enum>(value: &TEnum) -> Self {
166 let type_info = value.get_represented_type_info();
167 let mut dyn_enum = match value.variant_type() {
168 VariantType::Unit => DynamicEnum::new_with_index(
169 value.variant_index(),
170 value.variant_name(),
171 DynamicVariant::Unit,
172 ),
173 VariantType::Tuple => {
174 let mut data = DynamicTuple::default();
175 for field in value.iter_fields() {
176 data.insert_boxed(field.value().clone_value());
177 }
178 DynamicEnum::new_with_index(
179 value.variant_index(),
180 value.variant_name(),
181 DynamicVariant::Tuple(data),
182 )
183 }
184 VariantType::Struct => {
185 let mut data = DynamicStruct::default();
186 for field in value.iter_fields() {
187 let name = field.name().unwrap();
188 data.insert_boxed(name, field.value().clone_value());
189 }
190 DynamicEnum::new_with_index(
191 value.variant_index(),
192 value.variant_name(),
193 DynamicVariant::Struct(data),
194 )
195 }
196 };
197
198 dyn_enum.set_represented_type(type_info);
199 dyn_enum
200 }
201}
202
203impl Enum for DynamicEnum {
204 fn field(&self, name: &str) -> Option<&dyn Reflect> {
205 if let DynamicVariant::Struct(data) = &self.variant {
206 data.field(name)
207 } else {
208 None
209 }
210 }
211
212 fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
213 if let DynamicVariant::Tuple(data) = &self.variant {
214 data.field(index)
215 } else {
216 None
217 }
218 }
219
220 fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
221 if let DynamicVariant::Struct(data) = &mut self.variant {
222 data.field_mut(name)
223 } else {
224 None
225 }
226 }
227
228 fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
229 if let DynamicVariant::Tuple(data) = &mut self.variant {
230 data.field_mut(index)
231 } else {
232 None
233 }
234 }
235
236 fn index_of(&self, name: &str) -> Option<usize> {
237 if let DynamicVariant::Struct(data) = &self.variant {
238 data.index_of(name)
239 } else {
240 None
241 }
242 }
243
244 fn name_at(&self, index: usize) -> Option<&str> {
245 if let DynamicVariant::Struct(data) = &self.variant {
246 data.name_at(index)
247 } else {
248 None
249 }
250 }
251
252 fn iter_fields(&self) -> VariantFieldIter {
253 VariantFieldIter::new(self)
254 }
255
256 fn field_len(&self) -> usize {
257 match &self.variant {
258 DynamicVariant::Unit => 0,
259 DynamicVariant::Tuple(data) => data.field_len(),
260 DynamicVariant::Struct(data) => data.field_len(),
261 }
262 }
263
264 fn variant_name(&self) -> &str {
265 &self.variant_name
266 }
267
268 fn variant_index(&self) -> usize {
269 self.variant_index
270 }
271
272 fn variant_type(&self) -> VariantType {
273 match &self.variant {
274 DynamicVariant::Unit => VariantType::Unit,
275 DynamicVariant::Tuple(..) => VariantType::Tuple,
276 DynamicVariant::Struct(..) => VariantType::Struct,
277 }
278 }
279
280 fn clone_dynamic(&self) -> DynamicEnum {
281 Self {
282 represented_type: self.represented_type,
283 variant_index: self.variant_index,
284 variant_name: self.variant_name.clone(),
285 variant: self.variant.clone(),
286 }
287 }
288}
289
290impl Reflect for DynamicEnum {
291 #[inline]
292 fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
293 self.represented_type
294 }
295
296 #[inline]
297 fn into_any(self: Box<Self>) -> Box<dyn Any> {
298 self
299 }
300
301 #[inline]
302 fn as_any(&self) -> &dyn Any {
303 self
304 }
305
306 #[inline]
307 fn as_any_mut(&mut self) -> &mut dyn Any {
308 self
309 }
310
311 #[inline]
312 fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
313 self
314 }
315
316 #[inline]
317 fn as_reflect(&self) -> &dyn Reflect {
318 self
319 }
320
321 #[inline]
322 fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
323 self
324 }
325
326 #[inline]
327 fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
328 if let ReflectRef::Enum(value) = value.reflect_ref() {
329 if Enum::variant_name(self) == value.variant_name() {
330 match value.variant_type() {
332 VariantType::Struct => {
333 for field in value.iter_fields() {
334 let name = field.name().unwrap();
335 if let Some(v) = Enum::field_mut(self, name) {
336 v.try_apply(field.value())?;
337 }
338 }
339 }
340 VariantType::Tuple => {
341 for (index, field) in value.iter_fields().enumerate() {
342 if let Some(v) = Enum::field_at_mut(self, index) {
343 v.try_apply(field.value())?;
344 }
345 }
346 }
347 _ => {}
348 }
349 } else {
350 let dyn_variant = match value.variant_type() {
352 VariantType::Unit => DynamicVariant::Unit,
353 VariantType::Tuple => {
354 let mut dyn_tuple = DynamicTuple::default();
355 for field in value.iter_fields() {
356 dyn_tuple.insert_boxed(field.value().clone_value());
357 }
358 DynamicVariant::Tuple(dyn_tuple)
359 }
360 VariantType::Struct => {
361 let mut dyn_struct = DynamicStruct::default();
362 for field in value.iter_fields() {
363 dyn_struct
364 .insert_boxed(field.name().unwrap(), field.value().clone_value());
365 }
366 DynamicVariant::Struct(dyn_struct)
367 }
368 };
369 self.set_variant(value.variant_name(), dyn_variant);
370 }
371 } else {
372 return Err(ApplyError::MismatchedKinds {
373 from_kind: value.reflect_kind(),
374 to_kind: ReflectKind::Enum,
375 });
376 }
377 Ok(())
378 }
379
380 #[inline]
381 fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
382 *self = value.take()?;
383 Ok(())
384 }
385
386 #[inline]
387 fn reflect_kind(&self) -> ReflectKind {
388 ReflectKind::Enum
389 }
390
391 #[inline]
392 fn reflect_ref(&self) -> ReflectRef {
393 ReflectRef::Enum(self)
394 }
395
396 #[inline]
397 fn reflect_mut(&mut self) -> ReflectMut {
398 ReflectMut::Enum(self)
399 }
400
401 #[inline]
402 fn reflect_owned(self: Box<Self>) -> ReflectOwned {
403 ReflectOwned::Enum(self)
404 }
405
406 #[inline]
407 fn clone_value(&self) -> Box<dyn Reflect> {
408 Box::new(self.clone_dynamic())
409 }
410
411 #[inline]
412 fn reflect_hash(&self) -> Option<u64> {
413 enum_hash(self)
414 }
415
416 #[inline]
417 fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
418 enum_partial_eq(self, value)
419 }
420
421 #[inline]
422 fn debug(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
423 write!(f, "DynamicEnum(")?;
424 enum_debug(self, f)?;
425 write!(f, ")")
426 }
427
428 #[inline]
429 fn is_dynamic(&self) -> bool {
430 true
431 }
432}
433
434impl_type_path!((in bevy_reflect) DynamicEnum);