@@ -80,6 +80,11 @@ impl ReflectReference {
80
80
} )
81
81
}
82
82
83
+ /// Create a new reference to a value by allocating it.
84
+ ///
85
+ /// You can retrieve the allocator from the world using [`WorldGuard::allocator`].
86
+ /// Make sure to drop the allocator write guard before doing anything with the reference to prevent deadlocks.
87
+ ///
83
88
pub fn new_allocated < T : PartialReflect > (
84
89
value : T ,
85
90
allocator : & mut ReflectAllocator ,
@@ -547,3 +552,282 @@ impl Iterator for ReflectRefIter {
547
552
Some ( result)
548
553
}
549
554
}
555
+
556
+ #[ cfg( test) ]
557
+ mod test {
558
+ use bevy:: prelude:: { AppTypeRegistry , World } ;
559
+
560
+ use crate :: bindings:: {
561
+ function:: script_function:: AppScriptFunctionRegistry , AppReflectAllocator , WorldAccessGuard ,
562
+ } ;
563
+
564
+ use super :: * ;
565
+
566
+ #[ derive( Reflect , Component , Debug , Clone , PartialEq ) ]
567
+ struct Component ( Vec < String > ) ;
568
+
569
+ #[ derive( Reflect , Resource , Debug , Clone , PartialEq ) ]
570
+ struct Resource ( Vec < String > ) ;
571
+
572
+ fn setup_world ( ) -> World {
573
+ let mut world = World :: default ( ) ;
574
+
575
+ let type_registry = AppTypeRegistry :: default ( ) ;
576
+ {
577
+ let mut guard_type_registry = type_registry. write ( ) ;
578
+ guard_type_registry. register :: < Component > ( ) ;
579
+ guard_type_registry. register :: < Resource > ( ) ;
580
+ }
581
+
582
+ world. insert_resource ( type_registry) ;
583
+
584
+ let allocator = AppReflectAllocator :: default ( ) ;
585
+ world. insert_resource ( allocator) ;
586
+
587
+ let script_function_registry = AppScriptFunctionRegistry :: default ( ) ;
588
+ world. insert_resource ( script_function_registry) ;
589
+
590
+ world
591
+ }
592
+
593
+ #[ test]
594
+ fn test_component_ref ( ) {
595
+ let mut world = setup_world ( ) ;
596
+
597
+ let entity = world
598
+ . spawn ( Component ( vec ! [ "hello" . to_owned( ) , "world" . to_owned( ) ] ) )
599
+ . id ( ) ;
600
+
601
+ let world_guard = WorldGuard :: new ( WorldAccessGuard :: new ( & mut world) ) ;
602
+
603
+ let mut component_ref =
604
+ ReflectReference :: new_component_ref :: < Component > ( entity, world_guard. clone ( ) )
605
+ . expect ( "could not create component reference" ) ;
606
+
607
+ // index into component
608
+ assert_eq ! (
609
+ component_ref
610
+ . tail_type_id( world_guard. clone( ) )
611
+ . unwrap( )
612
+ . unwrap( ) ,
613
+ TypeId :: of:: <Component >( )
614
+ ) ;
615
+
616
+ component_ref
617
+ . with_reflect ( world_guard. clone ( ) , |s| {
618
+ let s = s. try_downcast_ref :: < Component > ( ) . unwrap ( ) ;
619
+ assert_eq ! ( s, & Component ( vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ) ;
620
+ } )
621
+ . unwrap ( ) ;
622
+
623
+ // index into vec field
624
+ component_ref. index_path ( ParsedPath :: parse_static ( ".0" ) . unwrap ( ) ) ;
625
+ assert_eq ! (
626
+ component_ref
627
+ . tail_type_id( world_guard. clone( ) )
628
+ . unwrap( )
629
+ . unwrap( ) ,
630
+ TypeId :: of:: <Vec <String >>( )
631
+ ) ;
632
+
633
+ assert_eq ! (
634
+ component_ref
635
+ . element_type_id( world_guard. clone( ) )
636
+ . unwrap( )
637
+ . unwrap( ) ,
638
+ TypeId :: of:: <String >( )
639
+ ) ;
640
+
641
+ assert_eq ! (
642
+ component_ref
643
+ . key_type_id( world_guard. clone( ) )
644
+ . unwrap( )
645
+ . unwrap( ) ,
646
+ TypeId :: of:: <usize >( )
647
+ ) ;
648
+
649
+ component_ref
650
+ . with_reflect ( world_guard. clone ( ) , |s| {
651
+ let s = s. try_downcast_ref :: < Vec < String > > ( ) . unwrap ( ) ;
652
+ assert_eq ! ( s, & vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ;
653
+ } )
654
+ . unwrap ( ) ;
655
+
656
+ // index into vec
657
+ component_ref. index_path ( ParsedPath :: parse_static ( "[0]" ) . unwrap ( ) ) ;
658
+
659
+ component_ref
660
+ . with_reflect ( world_guard. clone ( ) , |s| {
661
+ let s = s. try_downcast_ref :: < String > ( ) . unwrap ( ) ;
662
+ assert_eq ! ( s, "hello" ) ;
663
+ } )
664
+ . unwrap ( ) ;
665
+
666
+ assert_eq ! (
667
+ component_ref
668
+ . tail_type_id( world_guard. clone( ) )
669
+ . unwrap( )
670
+ . unwrap( ) ,
671
+ TypeId :: of:: <String >( )
672
+ ) ;
673
+ }
674
+
675
+ #[ test]
676
+ fn test_resource_ref ( ) {
677
+ let mut world = setup_world ( ) ;
678
+
679
+ world. insert_resource ( Resource ( vec ! [ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ) ;
680
+
681
+ let world_guard = WorldGuard :: new ( WorldAccessGuard :: new ( & mut world) ) ;
682
+
683
+ let mut resource_ref = ReflectReference :: new_resource_ref :: < Resource > ( world_guard. clone ( ) )
684
+ . expect ( "could not create resource reference" ) ;
685
+
686
+ // index into resource
687
+ assert_eq ! (
688
+ resource_ref
689
+ . tail_type_id( world_guard. clone( ) )
690
+ . unwrap( )
691
+ . unwrap( ) ,
692
+ TypeId :: of:: <Resource >( )
693
+ ) ;
694
+
695
+ resource_ref
696
+ . with_reflect ( world_guard. clone ( ) , |s| {
697
+ let s = s. try_downcast_ref :: < Resource > ( ) . unwrap ( ) ;
698
+ assert_eq ! ( s, & Resource ( vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ) ;
699
+ } )
700
+ . unwrap ( ) ;
701
+
702
+ // index into vec field
703
+ resource_ref. index_path ( ParsedPath :: parse_static ( ".0" ) . unwrap ( ) ) ;
704
+ assert_eq ! (
705
+ resource_ref
706
+ . tail_type_id( world_guard. clone( ) )
707
+ . unwrap( )
708
+ . unwrap( ) ,
709
+ TypeId :: of:: <Vec <String >>( )
710
+ ) ;
711
+
712
+ assert_eq ! (
713
+ resource_ref
714
+ . element_type_id( world_guard. clone( ) )
715
+ . unwrap( )
716
+ . unwrap( ) ,
717
+ TypeId :: of:: <String >( )
718
+ ) ;
719
+
720
+ assert_eq ! (
721
+ resource_ref
722
+ . key_type_id( world_guard. clone( ) )
723
+ . unwrap( )
724
+ . unwrap( ) ,
725
+ TypeId :: of:: <usize >( )
726
+ ) ;
727
+
728
+ resource_ref
729
+ . with_reflect ( world_guard. clone ( ) , |s| {
730
+ let s = s. try_downcast_ref :: < Vec < String > > ( ) . unwrap ( ) ;
731
+ assert_eq ! ( s, & vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ;
732
+ } )
733
+ . unwrap ( ) ;
734
+
735
+ // index into vec
736
+ resource_ref. index_path ( ParsedPath :: parse_static ( "[0]" ) . unwrap ( ) ) ;
737
+
738
+ resource_ref
739
+ . with_reflect ( world_guard. clone ( ) , |s| {
740
+ let s = s. try_downcast_ref :: < String > ( ) . unwrap ( ) ;
741
+ assert_eq ! ( s, "hello" ) ;
742
+ } )
743
+ . unwrap ( ) ;
744
+
745
+ assert_eq ! (
746
+ resource_ref
747
+ . tail_type_id( world_guard. clone( ) )
748
+ . unwrap( )
749
+ . unwrap( ) ,
750
+ TypeId :: of:: <String >( )
751
+ ) ;
752
+ }
753
+
754
+ #[ test]
755
+ fn test_allocation_ref ( ) {
756
+ let mut world = setup_world ( ) ;
757
+
758
+ let value = Component ( vec ! [ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ;
759
+
760
+ let world_guard = WorldGuard :: new ( WorldAccessGuard :: new ( & mut world) ) ;
761
+ let allocator = world_guard. allocator ( ) ;
762
+ let mut allocator_write = allocator. write ( ) ;
763
+ let mut allocation_ref = ReflectReference :: new_allocated ( value, & mut allocator_write) ;
764
+ drop ( allocator_write) ;
765
+
766
+ // index into component
767
+ assert_eq ! (
768
+ allocation_ref
769
+ . tail_type_id( world_guard. clone( ) )
770
+ . unwrap( )
771
+ . unwrap( ) ,
772
+ TypeId :: of:: <Component >( )
773
+ ) ;
774
+
775
+ allocation_ref
776
+ . with_reflect ( world_guard. clone ( ) , |s| {
777
+ let s = s. try_downcast_ref :: < Component > ( ) . unwrap ( ) ;
778
+ assert_eq ! ( s, & Component ( vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ) ;
779
+ } )
780
+ . unwrap ( ) ;
781
+
782
+ // index into vec field
783
+ allocation_ref. index_path ( ParsedPath :: parse_static ( ".0" ) . unwrap ( ) ) ;
784
+ assert_eq ! (
785
+ allocation_ref
786
+ . tail_type_id( world_guard. clone( ) )
787
+ . unwrap( )
788
+ . unwrap( ) ,
789
+ TypeId :: of:: <Vec <String >>( )
790
+ ) ;
791
+
792
+ assert_eq ! (
793
+ allocation_ref
794
+ . element_type_id( world_guard. clone( ) )
795
+ . unwrap( )
796
+ . unwrap( ) ,
797
+ TypeId :: of:: <String >( )
798
+ ) ;
799
+
800
+ assert_eq ! (
801
+ allocation_ref
802
+ . key_type_id( world_guard. clone( ) )
803
+ . unwrap( )
804
+ . unwrap( ) ,
805
+ TypeId :: of:: <usize >( )
806
+ ) ;
807
+
808
+ allocation_ref
809
+ . with_reflect ( world_guard. clone ( ) , |s| {
810
+ let s = s. try_downcast_ref :: < Vec < String > > ( ) . unwrap ( ) ;
811
+ assert_eq ! ( s, & vec![ "hello" . to_owned( ) , "world" . to_owned( ) ] ) ;
812
+ } )
813
+ . unwrap ( ) ;
814
+
815
+ // index into vec
816
+ allocation_ref. index_path ( ParsedPath :: parse_static ( "[0]" ) . unwrap ( ) ) ;
817
+
818
+ allocation_ref
819
+ . with_reflect ( world_guard. clone ( ) , |s| {
820
+ let s = s. try_downcast_ref :: < String > ( ) . unwrap ( ) ;
821
+ assert_eq ! ( s, "hello" ) ;
822
+ } )
823
+ . unwrap ( ) ;
824
+
825
+ assert_eq ! (
826
+ allocation_ref
827
+ . tail_type_id( world_guard. clone( ) )
828
+ . unwrap( )
829
+ . unwrap( ) ,
830
+ TypeId :: of:: <String >( )
831
+ ) ;
832
+ }
833
+ }
0 commit comments