1- use std :: iter :: FusedIterator ;
1+ //! Additional utilities for `Vec` stores.
22
3- use crate :: { impls:: index:: IndexWrite , store:: Store } ;
4- use dioxus_signals:: { Readable , ReadableExt } ;
3+ use std:: { iter:: FusedIterator , panic:: Location } ;
4+
5+ use crate :: { impls:: index:: IndexSelector , store:: Store , ReadStore } ;
6+ use dioxus_signals:: {
7+ AnyStorage , BorrowError , BorrowMutError , ReadSignal , Readable , ReadableExt , UnsyncStorage ,
8+ Writable , WriteLock , WriteSignal ,
9+ } ;
10+ use generational_box:: ValueDroppedError ;
511
612impl < Lens , I > Store < Vec < I > , Lens >
713where
@@ -46,16 +52,18 @@ where
4652 /// println!("{}", item);
4753 /// }
4854 /// ```
55+ #[ track_caller]
4956 pub fn iter (
5057 & self ,
51- ) -> impl ExactSizeIterator < Item = Store < I , IndexWrite < usize , Lens > > >
58+ ) -> impl ExactSizeIterator < Item = Store < I , VecGetWrite < Lens > > >
5259 + DoubleEndedIterator
5360 + FusedIterator
5461 + ' _
5562 where
5663 Lens : Clone ,
5764 {
58- ( 0 ..self . len ( ) ) . map ( move |i| self . clone ( ) . index ( i) )
65+ let location = Location :: caller ( ) ;
66+ ( 0 ..self . len ( ) ) . map ( move |i| self . clone ( ) . get_unchecked_at ( i, location) )
5967 }
6068
6169 /// Try to get an item from slice. This will only track the shallow state of the slice.
@@ -70,14 +78,130 @@ where
7078 /// // The indexed store can access the store methods of the indexed store.
7179 /// assert_eq!(indexed_store(), 2);
7280 /// ```
73- pub fn get ( & self , index : usize ) -> Option < Store < I , IndexWrite < usize , Lens > > >
81+ pub fn get ( & self , index : usize ) -> Option < Store < I , VecGetWrite < Lens > > >
7482 where
7583 Lens : Clone ,
7684 {
7785 if index >= self . len ( ) {
7886 None
7987 } else {
80- Some ( self . clone ( ) . index ( index) )
88+ Some ( self . clone ( ) . get_unchecked ( index) )
8189 }
8290 }
91+
92+ /// Get a store for the item at the given index without checking if it is in bounds.
93+ ///
94+ /// This is not unsafe, but reads will return a [BorrowError::Dropped] error if the index is out of bounds.
95+ #[ track_caller]
96+ pub fn get_unchecked ( self , index : usize ) -> Store < I , VecGetWrite < Lens > > {
97+ self . get_unchecked_at ( index, Location :: caller ( ) )
98+ }
99+
100+ fn get_unchecked_at (
101+ self ,
102+ index : usize ,
103+ location : & ' static Location < ' static > ,
104+ ) -> Store < I , VecGetWrite < Lens > > {
105+ <Vec < I > >:: scope_selector ( self . into_selector ( ) , & index)
106+ . map_writer ( move |write| VecGetWrite {
107+ index,
108+ write,
109+ created : location,
110+ } )
111+ . into ( )
112+ }
113+ }
114+
115+ /// A specific index in a `Readable` / `Writable` Vec that uses safe `.get()` / `.get_mut()` access.
116+ #[ derive( Clone , Copy ) ]
117+ pub struct VecGetWrite < Write > {
118+ index : usize ,
119+ write : Write ,
120+ created : & ' static Location < ' static > ,
121+ }
122+
123+ impl < Write , T > Readable for VecGetWrite < Write >
124+ where
125+ Write : Readable < Target = Vec < T > > ,
126+ T : ' static ,
127+ {
128+ type Target = T ;
129+ type Storage = Write :: Storage ;
130+
131+ fn try_read_unchecked ( & self ) -> Result < dioxus_signals:: ReadableRef < ' static , Self > , BorrowError >
132+ where
133+ Self :: Target : ' static ,
134+ {
135+ self . write . try_read_unchecked ( ) . and_then ( |value| {
136+ let index = self . index ;
137+ Self :: Storage :: try_map ( value, move |value : & Vec < T > | value. get ( index) )
138+ . ok_or_else ( || BorrowError :: Dropped ( ValueDroppedError :: new ( self . created ) ) )
139+ } )
140+ }
141+
142+ fn try_peek_unchecked ( & self ) -> Result < dioxus_signals:: ReadableRef < ' static , Self > , BorrowError >
143+ where
144+ Self :: Target : ' static ,
145+ {
146+ self . write . try_peek_unchecked ( ) . and_then ( |value| {
147+ let index = self . index ;
148+ Self :: Storage :: try_map ( value, move |value : & Vec < T > | value. get ( index) )
149+ . ok_or_else ( || BorrowError :: Dropped ( ValueDroppedError :: new ( self . created ) ) )
150+ } )
151+ }
152+
153+ fn subscribers ( & self ) -> dioxus_core:: Subscribers
154+ where
155+ Self :: Target : ' static ,
156+ {
157+ self . write . subscribers ( )
158+ }
159+ }
160+
161+ impl < Write , T > Writable for VecGetWrite < Write >
162+ where
163+ Write : Writable < Target = Vec < T > > ,
164+ T : ' static ,
165+ {
166+ type WriteMetadata = Write :: WriteMetadata ;
167+
168+ fn try_write_unchecked (
169+ & self ,
170+ ) -> Result < dioxus_signals:: WritableRef < ' static , Self > , BorrowMutError >
171+ where
172+ Self :: Target : ' static ,
173+ {
174+ self . write . try_write_unchecked ( ) . and_then ( |value| {
175+ let index = self . index ;
176+ WriteLock :: filter_map ( value, move |value : & mut Vec < T > | value. get_mut ( index) )
177+ . ok_or_else ( || BorrowMutError :: Dropped ( ValueDroppedError :: new ( self . created ) ) )
178+ } )
179+ }
180+ }
181+
182+ impl < T , Write > :: std:: convert:: From < Store < T , VecGetWrite < Write > > > for Store < T , WriteSignal < T > >
183+ where
184+ Write : Writable < Target = Vec < T > , Storage = UnsyncStorage > + ' static ,
185+ Write :: WriteMetadata : ' static ,
186+ T : ' static ,
187+ {
188+ fn from ( value : Store < T , VecGetWrite < Write > > ) -> Self {
189+ value
190+ . into_selector ( )
191+ . map_writer ( |writer| WriteSignal :: new ( writer) )
192+ . into ( )
193+ }
194+ }
195+
196+ impl < T , Write > :: std:: convert:: From < Store < T , VecGetWrite < Write > > > for ReadStore < T >
197+ where
198+ Write : Readable < Target = Vec < T > , Storage = UnsyncStorage > + ' static ,
199+ T : ' static ,
200+ {
201+ fn from ( value : Store < T , VecGetWrite < Write > > ) -> Self {
202+ value
203+ . into_selector ( )
204+ . map_writer ( |writer| ReadSignal :: new ( writer) )
205+ . into ( )
206+ }
83207}
0 commit comments