@@ -54,7 +54,7 @@ pub enum HandleKind {
5454 } ,
5555}
5656
57- pub enum ResourceKind {
57+ enum ResourceKind {
5858 /// Represents an owned resource handle with the listed representation.
5959 ///
6060 /// The `lend_count` tracks how many times this has been lent out as a
@@ -74,6 +74,14 @@ pub enum ResourceKind {
7474 } ,
7575}
7676
77+ /// Return value from [`HandleTable::remove_resource`].
78+ pub enum RemovedResource {
79+ /// An `own` resource was removed with the specified `rep`
80+ Own { rep : u32 } ,
81+ /// A `borrow` resource was removed originally created within `scope`.
82+ Borrow { scope : usize } ,
83+ }
84+
7785enum Slot {
7886 Free { next : u32 } ,
7987 Handle { rep : u32 , kind : HandleKind } ,
@@ -132,38 +140,48 @@ impl HandleTable {
132140 Ok ( ret)
133141 }
134142
135- pub fn insert_resource ( & mut self , kind : ResourceKind ) -> Result < u32 > {
136- self . insert ( Slot :: Resource { kind } )
143+ fn handle_index_to_table_index ( & self , idx : u32 ) -> Option < usize > {
144+ // NB: `idx` is decremented by one to account for the `+1` above during
145+ // allocation.
146+ let idx = idx. checked_sub ( 1 ) ?;
147+ usize:: try_from ( idx) . ok ( )
137148 }
138149
139- pub fn insert_handle ( & mut self , rep : u32 , kind : HandleKind ) -> Result < u32 > {
140- if matches ! ( self
141- . reps_to_indexes
142- . get( usize :: try_from( rep) . unwrap( ) ) , Some ( idx) if * idx != 0 )
143- {
144- bail ! ( "rep {rep} already exists in this table" ) ;
145- }
146-
147- let ret = self . insert ( Slot :: Handle { rep, kind } ) ?;
148-
149- let rep = usize:: try_from ( rep) . unwrap ( ) ;
150- if self . reps_to_indexes . len ( ) <= rep {
151- self . reps_to_indexes . resize ( rep. checked_add ( 1 ) . unwrap ( ) , 0 ) ;
150+ fn get_mut ( & mut self , idx : u32 ) -> Result < & mut Slot > {
151+ let slot = self
152+ . handle_index_to_table_index ( idx)
153+ . and_then ( |i| self . slots . get_mut ( i) ) ;
154+ match slot {
155+ None | Some ( Slot :: Free { .. } ) => bail ! ( "unknown handle index {idx}" ) ,
156+ Some ( slot) => Ok ( slot) ,
152157 }
158+ }
153159
154- self . reps_to_indexes [ rep] = ret;
155-
156- Ok ( ret)
160+ /// Inserts a new `own` resource into this table whose type/rep are
161+ /// specified by `resource`.
162+ pub fn insert_own_resource ( & mut self , resource : TypedResource ) -> Result < u32 > {
163+ self . insert ( Slot :: Resource {
164+ kind : ResourceKind :: Own {
165+ resource,
166+ lend_count : 0 ,
167+ } ,
168+ } )
157169 }
158170
159- fn handle_index_to_table_index ( & self , idx : u32 ) -> Option < usize > {
160- // NB: `idx` is decremented by one to account for the `+1` above during
161- // allocation.
162- let idx = idx. checked_sub ( 1 ) ?;
163- usize:: try_from ( idx) . ok ( )
171+ /// Inserts a new `borrow` resource into this table whose type/rep are
172+ /// specified by `resource`. The `scope` specified is used by
173+ /// `CallContexts` to manage lending information.
174+ pub fn insert_borrow_resource ( & mut self , resource : TypedResource , scope : usize ) -> Result < u32 > {
175+ self . insert ( Slot :: Resource {
176+ kind : ResourceKind :: Borrow { resource, scope } ,
177+ } )
164178 }
165179
166- pub ( super ) fn resource_rep ( & self , idx : TypedResourceIndex ) -> Result < u32 > {
180+ /// Returns the internal "rep" of the resource specified by `idx`.
181+ ///
182+ /// Returns an error if `idx` is out-of-bounds or doesn't point to a
183+ /// resource of the appropriate type.
184+ pub fn resource_rep ( & self , idx : TypedResourceIndex ) -> Result < u32 > {
167185 let slot = self
168186 . handle_index_to_table_index ( idx. raw_index ( ) )
169187 . and_then ( |i| self . slots . get ( i) ) ;
@@ -178,30 +196,101 @@ impl HandleTable {
178196 }
179197 }
180198
181- fn get_mut ( & mut self , idx : u32 ) -> Result < & mut Slot > {
182- let slot = self
183- . handle_index_to_table_index ( idx)
184- . and_then ( |i| self . slots . get_mut ( i) ) ;
185- match slot {
186- None | Some ( Slot :: Free { .. } ) => bail ! ( "unknown handle index {idx}" ) ,
187- Some ( slot) => Ok ( slot) ,
199+ /// Accesses the "rep" of the resource pointed to by `idx` as part of a
200+ /// lending operation.
201+ ///
202+ /// This will increase `lend_count` for owned resources and must be paired
203+ /// with a `resource_undo_lend` below later on (managed by `CallContexts`).
204+ ///
205+ /// Upon success returns the "rep" plus whether the borrow came from an
206+ /// `own` handle.
207+ pub fn resource_lend ( & mut self , idx : TypedResourceIndex ) -> Result < ( u32 , bool ) > {
208+ match self . get_mut ( idx. raw_index ( ) ) ? {
209+ Slot :: Resource {
210+ kind :
211+ ResourceKind :: Own {
212+ resource,
213+ lend_count,
214+ } ,
215+ } => {
216+ let rep = resource. rep ( & idx) ?;
217+ * lend_count = lend_count. checked_add ( 1 ) . unwrap ( ) ;
218+ Ok ( ( rep, true ) )
219+ }
220+ Slot :: Resource {
221+ kind : ResourceKind :: Borrow { resource, .. } ,
222+ } => Ok ( ( resource. rep ( & idx) ?, false ) ) ,
223+ _ => bail ! ( "index {} is not a resource" , idx. raw_index( ) ) ,
188224 }
189225 }
190226
191- pub ( super ) fn get_mut_resource (
192- & mut self ,
193- idx : TypedResourceIndex ,
194- ) -> Result < & mut ResourceKind > {
195- let slot = self
196- . handle_index_to_table_index ( idx. raw_index ( ) )
197- . and_then ( |i| self . slots . get_mut ( i) ) ;
198- match slot {
199- None | Some ( Slot :: Free { .. } ) => bail ! ( "unknown handle index {}" , idx. raw_index( ) ) ,
200- Some ( Slot :: Handle { .. } ) => {
201- bail ! ( "index {} is a handle, not a resource" , idx. raw_index( ) )
227+ /// For `own` resources that were borrowed in `resource_lend`, undoes the
228+ /// lending operation.
229+ pub fn resource_undo_lend ( & mut self , idx : TypedResourceIndex ) -> Result < ( ) > {
230+ match self . get_mut ( idx. raw_index ( ) ) ? {
231+ Slot :: Resource {
232+ kind : ResourceKind :: Own { lend_count, .. } ,
233+ } => {
234+ * lend_count -= 1 ;
235+ Ok ( ( ) )
236+ }
237+ _ => bail ! ( "index {} is not an own resource" , idx. raw_index( ) ) ,
238+ }
239+ }
240+
241+ /// Removes the resource specified by `idx` from the table.
242+ ///
243+ /// This can fail if `idx` doesn't point to a resource, points to a
244+ /// borrowed resource, or points to a resource of the wrong type.
245+ pub fn remove_resource ( & mut self , idx : TypedResourceIndex ) -> Result < RemovedResource > {
246+ let to_fill = Slot :: Free { next : self . next } ;
247+ let slot = self . get_mut ( idx. raw_index ( ) ) ?;
248+ let ret = match slot {
249+ Slot :: Resource {
250+ kind :
251+ ResourceKind :: Own {
252+ resource,
253+ lend_count,
254+ } ,
255+ } => {
256+ if * lend_count != 0 {
257+ bail ! ( "cannot remove owned resource while borrowed" )
258+ }
259+ RemovedResource :: Own {
260+ rep : resource. rep ( & idx) ?,
261+ }
262+ }
263+ Slot :: Resource {
264+ kind : ResourceKind :: Borrow { resource, scope } ,
265+ } => {
266+ // Ensure the drop is done with the right type
267+ resource. rep ( & idx) ?;
268+ RemovedResource :: Borrow { scope : * scope }
202269 }
203- Some ( Slot :: Resource { kind } ) => Ok ( kind) ,
270+ _ => bail ! ( "index {} is not a resource" , idx. raw_index( ) ) ,
271+ } ;
272+ * slot = to_fill;
273+ Ok ( ret)
274+ }
275+
276+ pub fn insert_handle ( & mut self , rep : u32 , kind : HandleKind ) -> Result < u32 > {
277+ if matches ! ( self
278+ . reps_to_indexes
279+ . get( usize :: try_from( rep) . unwrap( ) ) , Some ( idx) if * idx != 0 )
280+ {
281+ bail ! ( "rep {rep} already exists in this table" ) ;
282+ }
283+
284+ let ret = self . insert ( Slot :: Handle { rep, kind } ) ?;
285+
286+ let rep = usize:: try_from ( rep) . unwrap ( ) ;
287+ if self . reps_to_indexes . len ( ) <= rep {
288+ self . reps_to_indexes . resize ( rep. checked_add ( 1 ) . unwrap ( ) , 0 ) ;
204289 }
290+
291+ self . reps_to_indexes [ rep] = ret;
292+
293+ Ok ( ret)
205294 }
206295
207296 pub fn get_mut_handle_by_index ( & mut self , idx : u32 ) -> Result < ( u32 , & mut HandleKind ) > {
@@ -225,17 +314,6 @@ impl HandleTable {
225314 }
226315 }
227316
228- pub ( super ) fn remove_resource ( & mut self , idx : TypedResourceIndex ) -> Result < ResourceKind > {
229- _ = self . resource_rep ( idx) ?;
230-
231- let to_fill = Slot :: Free { next : self . next } ;
232- let Slot :: Resource { kind } = mem:: replace ( self . get_mut ( idx. raw_index ( ) ) ?, to_fill) else {
233- unreachable ! ( )
234- } ;
235- self . next = idx. raw_index ( ) - 1 ;
236- Ok ( kind)
237- }
238-
239317 pub fn remove_handle_by_index ( & mut self , idx : u32 ) -> Result < ( u32 , HandleKind ) > {
240318 _ = self . get_mut_handle_by_index ( idx) ?;
241319
0 commit comments