@@ -245,8 +245,20 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
245
245
self . first . is_null ( )
246
246
}
247
247
248
- /// Add the provided item to the back of the list.
249
- pub fn push_back ( & mut self , item : ListArc < T , ID > ) {
248
+ /// Inserts `item` before `next` in the cycle.
249
+ ///
250
+ /// Returns a pointer to the newly inserted element. Never changes `self.first` unless the list
251
+ /// is empty.
252
+ ///
253
+ /// # Safety
254
+ ///
255
+ /// * `next` must be an element in this list or null.
256
+ /// * if `next` is null, then the list must be empty.
257
+ unsafe fn insert_inner (
258
+ & mut self ,
259
+ item : ListArc < T , ID > ,
260
+ next : * mut ListLinksFields ,
261
+ ) -> * mut ListLinksFields {
250
262
let raw_item = ListArc :: into_raw ( item) ;
251
263
// SAFETY:
252
264
// * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
@@ -259,16 +271,16 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
259
271
// SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
260
272
let item = unsafe { ListLinks :: fields ( list_links) } ;
261
273
262
- if self . first . is_null ( ) {
263
- self . first = item ;
274
+ // Check if the list is empty.
275
+ if next . is_null ( ) {
264
276
// SAFETY: The caller just gave us ownership of these fields.
265
277
// INVARIANT: A linked list with one item should be cyclic.
266
278
unsafe {
267
279
( * item) . next = item;
268
280
( * item) . prev = item;
269
281
}
282
+ self . first = item;
270
283
} else {
271
- let next = self . first ;
272
284
// SAFETY: By the type invariant, this pointer is valid or null. We just checked that
273
285
// it's not null, so it must be valid.
274
286
let prev = unsafe { ( * next) . prev } ;
@@ -282,45 +294,27 @@ impl<T: ?Sized + ListItem<ID>, const ID: u64> List<T, ID> {
282
294
( * next) . prev = item;
283
295
}
284
296
}
297
+
298
+ item
299
+ }
300
+
301
+ /// Add the provided item to the back of the list.
302
+ pub fn push_back ( & mut self , item : ListArc < T , ID > ) {
303
+ // SAFETY:
304
+ // * `self.first` is null or in the list.
305
+ // * `self.first` is only null if the list is empty.
306
+ unsafe { self . insert_inner ( item, self . first ) } ;
285
307
}
286
308
287
309
/// Add the provided item to the front of the list.
288
310
pub fn push_front ( & mut self , item : ListArc < T , ID > ) {
289
- let raw_item = ListArc :: into_raw ( item) ;
290
311
// SAFETY:
291
- // * We just got `raw_item` from a `ListArc`, so it's in an `Arc`.
292
- // * If this requirement is violated, then the previous caller of `prepare_to_insert`
293
- // violated the safety requirement that they can't give up ownership of the `ListArc`
294
- // until they call `post_remove`.
295
- // * We own the `ListArc`.
296
- // * Removing items] from this list is always done using `remove_internal_inner`, which
297
- // calls `post_remove` before giving up ownership.
298
- let list_links = unsafe { T :: prepare_to_insert ( raw_item) } ;
299
- // SAFETY: We have not yet called `post_remove`, so `list_links` is still valid.
300
- let item = unsafe { ListLinks :: fields ( list_links) } ;
312
+ // * `self.first` is null or in the list.
313
+ // * `self.first` is only null if the list is empty.
314
+ let new_elem = unsafe { self . insert_inner ( item, self . first ) } ;
301
315
302
- if self . first . is_null ( ) {
303
- // SAFETY: The caller just gave us ownership of these fields.
304
- // INVARIANT: A linked list with one item should be cyclic.
305
- unsafe {
306
- ( * item) . next = item;
307
- ( * item) . prev = item;
308
- }
309
- } else {
310
- let next = self . first ;
311
- // SAFETY: We just checked that `next` is non-null.
312
- let prev = unsafe { ( * next) . prev } ;
313
- // SAFETY: Pointers in a linked list are never dangling, and the caller just gave us
314
- // ownership of the fields on `item`.
315
- // INVARIANT: This correctly inserts `item` between `prev` and `next`.
316
- unsafe {
317
- ( * item) . next = next;
318
- ( * item) . prev = prev;
319
- ( * prev) . next = item;
320
- ( * next) . prev = item;
321
- }
322
- }
323
- self . first = item;
316
+ // INVARIANT: `new_elem` is in the list because we just inserted it.
317
+ self . first = new_elem;
324
318
}
325
319
326
320
/// Removes the last item from this list.
0 commit comments