@@ -177,6 +177,7 @@ use std::{
177
177
cell:: RefCell ,
178
178
collections:: { BTreeMap , HashMap } ,
179
179
fmt, panic,
180
+ rc:: Rc ,
180
181
} ;
181
182
182
183
/// Creates a scope.
@@ -796,3 +797,127 @@ impl ScopeInner {
796
797
}
797
798
}
798
799
}
800
+
801
+ /// A builder for constructing cyclic data structures within a [Scope].
802
+ ///
803
+ /// The [Cyclic] struct provides an interface for creating sets of
804
+ /// objects with cyclic (self-referential or mutually referential)
805
+ /// relationships. It automates the creation and storage of [Rc] and
806
+ /// [Weak](std::rc::Weak) pointers in the given scope, enabling the
807
+ /// construction of graphs, trees with back-references, or other cyclic
808
+ /// structures.
809
+ ///
810
+ /// # How It Works #
811
+ ///
812
+ /// - Each call to [then](Cyclic::then) registers a constructor closure
813
+ /// associated with a unique name.
814
+ /// - When [construct](Cyclic::construct) is called:
815
+ /// - All registered names are first populated in the scope as `{name}/weak`
816
+ /// keys, each holding a `Weak<R>` reference to the eventual value.
817
+ /// - Then, each closure is executed in order, allowing each to access the
818
+ /// previously registered strong and weak references via the scope.
819
+ /// - The resulting value of each closure is stored under its name as a strong
820
+ /// [Rc] reference.
821
+ ///
822
+ /// This allows closures to refer to both earlier and later entries. Later
823
+ /// entries can only be weakly referenced. Earlier entries can be strongly
824
+ /// referenced.
825
+ ///
826
+ /// # Examples #
827
+ ///
828
+ /// ```
829
+ /// use bypass::{scope, Cyclic};
830
+ /// use std::rc::{Rc, Weak};
831
+ ///
832
+ /// scope!(static MAIN);
833
+ ///
834
+ /// MAIN.scope(|| {
835
+ /// Cyclic::new(&MAIN, |_| {})
836
+ /// .then("first", || {
837
+ /// // Access a weak reference to a subsequent `then` entry.
838
+ /// let weak_second: Weak<String> = MAIN.get("second/weak");
839
+ /// println!("first: Strong count of 'second': {}", Weak::strong_count(&weak_second));
840
+ ///
841
+ /// 123i32
842
+ /// })
843
+ /// .then("second", || {
844
+ /// // Access a strong reference to a previous `then` entry.
845
+ /// let strong_first: Rc<i32> = MAIN.get("first");
846
+ /// println!("second: Value of 'first': {}", *strong_first);
847
+ /// String::from("lorem ipsum")
848
+ /// })
849
+ /// .construct();
850
+ /// });
851
+ /// ```
852
+ pub struct Cyclic < F : FnOnce ( & ' static Scope ) > {
853
+ scope : & ' static Scope ,
854
+ function : F ,
855
+ }
856
+
857
+ impl < X : FnOnce ( & ' static Scope ) > Cyclic < X > {
858
+ /// Creates a new cyclic builder with an initializer.
859
+ ///
860
+ /// Function `initializer` will be run before all [then](Cyclic::then)
861
+ /// clauses, but after all weak pointers have been added to the scope.
862
+ ///
863
+ /// # Examples #
864
+ ///
865
+ /// ```
866
+ /// use bypass::{scope, Cyclic};
867
+ /// use std::rc::{Rc, Weak};
868
+ ///
869
+ /// scope!(static MAIN);
870
+ ///
871
+ /// MAIN.scope(|| {
872
+ /// Cyclic::new(&MAIN, |scope| {
873
+ /// scope.insert("x", 123);
874
+ /// // We can get a weak pointer to subsequent `then`s.
875
+ /// let y: Weak<usize> = scope.get("y/weak");
876
+ /// })
877
+ /// .then("y", || {
878
+ /// let value: i32 = MAIN.get("x");
879
+ /// assert_eq!(value, 123);
880
+ ///
881
+ /// 9usize
882
+ /// })
883
+ /// .construct();
884
+ /// });
885
+ /// ```
886
+ pub fn new ( scope : & ' static Scope , initializer : X ) -> Self {
887
+ Self {
888
+ scope,
889
+ function : initializer,
890
+ }
891
+ }
892
+ }
893
+
894
+ impl < F : FnOnce ( & ' static Scope ) > Cyclic < F > {
895
+ /// Adds a cyclic dependency.
896
+ pub fn then < N : Into < CowStr > , G : FnOnce ( ) -> R , R : ' static > (
897
+ self ,
898
+ name : N ,
899
+ g : G ,
900
+ ) -> Cyclic < impl FnOnce ( & ' static Scope ) > {
901
+ let scope = self . scope ;
902
+ let function = self . function ;
903
+ let name = name. into ( ) ;
904
+
905
+ Cyclic {
906
+ scope,
907
+ function : move |scope| {
908
+ let name_clone = name. clone ( ) ;
909
+ let strong = Rc :: new_cyclic ( |weak| {
910
+ scope. insert ( format ! ( "{}/weak" , name_clone) , weak. clone ( ) ) ;
911
+ function ( scope) ;
912
+ g ( )
913
+ } ) ;
914
+ scope. insert ( name, strong) ;
915
+ } ,
916
+ }
917
+ }
918
+
919
+ /// Constructs the set of cyclic dependencies.
920
+ pub fn construct ( self ) {
921
+ ( self . function ) ( self . scope ) ;
922
+ }
923
+ }
0 commit comments