1#![warn(
154 clippy::pedantic,
155 missing_debug_implementations,
156 missing_docs,
157 noop_method_call,
158 trivial_casts,
159 trivial_numeric_casts,
160 unsafe_op_in_unsafe_fn,
161 unused_lifetimes,
162 unused_qualifications
163)]
164#![allow(
165 clippy::items_after_statements,
166
167 clippy::type_repetition_in_bounds,
169
170 clippy::transmute_ptr_to_ptr,
172
173 clippy::redundant_closure,
175
176 clippy::module_name_repetitions,
178)]
179#![no_std]
180
181#[cfg(feature = "alloc")]
182extern crate alloc;
183
184#[cfg(feature = "std")]
185extern crate std;
186
187pub mod id;
188pub use id::Id;
189
190mod list;
191pub use list::{Cursor, CursorMut, PinList, Types};
192
193mod node;
194pub use node::{InitializedNode, Node, NodeData};
195
196mod util;
197
198#[cfg(all(test, feature = "std"))]
199mod tests {
200 use crate::id;
201 use core::pin::Pin;
202 use pin_utils::pin_mut as pin;
203 use std::boxed::Box;
204 use std::panic;
205 use std::process::abort;
206 use std::ptr;
207
208 type PinListTypes = dyn crate::Types<
209 Id = id::Checked,
210 Protected = Box<u8>,
212 Removed = Box<u16>,
213 Unprotected = Box<u32>,
214 >;
215 type PinList = crate::PinList<PinListTypes>;
216
217 #[test]
218 fn empty_lists() {
219 let mut list = PinList::new(id::Checked::new());
220 let list_ptr: *const _ = &list;
221
222 let assert_ghost_cursor = |cursor: crate::Cursor<'_, _>| {
223 assert!(ptr::eq(cursor.list(), list_ptr));
224 assert_eq!(cursor.protected(), None);
225 assert_eq!(cursor.unprotected(), None);
226 };
227 let assert_ghost_cursor_mut = |mut cursor: crate::CursorMut<'_, _>| {
228 assert!(ptr::eq(cursor.list(), list_ptr));
229 assert_eq!(cursor.protected(), None);
230 assert_eq!(cursor.protected_mut(), None);
231 assert_eq!(cursor.unprotected(), None);
232 assert_eq!(cursor.remove_current(Box::new(5)), Err(Box::new(5)));
233 assert!(!cursor.remove_current_with(|_| abort()));
234 assert!(!cursor.remove_current_with_or(|_| abort(), || abort()));
235 assert_ghost_cursor(cursor.as_shared());
236 };
237
238 assert!(list.is_empty());
239
240 assert_ghost_cursor(list.cursor_ghost());
241 assert_ghost_cursor(list.cursor_front());
242 assert_ghost_cursor(list.cursor_back());
243 assert_ghost_cursor_mut(list.cursor_ghost_mut());
244 assert_ghost_cursor_mut(list.cursor_front_mut());
245 assert_ghost_cursor_mut(list.cursor_back_mut());
246 }
247
248 #[test]
249 fn single_node_with_unlink() {
250 let mut list = PinList::new(id::Checked::new());
251
252 let node = crate::Node::new();
253 pin!(node);
254 assert!(node.is_initial());
255 assert!(node.initialized().is_none());
256 assert!(node.as_mut().initialized_mut().is_none());
257
258 let mut protected = Box::new(0);
259 let unprotected = Box::new(1);
260 list.push_front(node.as_mut(), protected.clone(), unprotected.clone());
261
262 assert!(!node.is_initial());
263
264 let initialized = node.initialized().unwrap();
265 assert_eq!(initialized.unprotected(), &unprotected);
266 assert_eq!(initialized.protected(&list), Some(&protected));
267 assert_eq!(initialized.protected_mut(&mut list), Some(&mut protected));
268
269 let initialized = node.as_mut().initialized_mut().unwrap();
270 assert_eq!(initialized.unprotected(), &unprotected);
271 assert_eq!(initialized.protected(&list), Some(&protected));
272 assert_eq!(initialized.protected_mut(&mut list), Some(&mut protected));
273
274 assert!(!list.is_empty());
275
276 let check_cursor = |mut cursor: crate::Cursor<'_, _>| {
277 assert_eq!(cursor.protected().unwrap(), &protected);
278 assert_eq!(cursor.unprotected().unwrap(), &unprotected);
279 cursor.move_next();
280 assert_eq!(cursor.protected(), None);
281 for _ in 0..10 {
282 cursor.move_previous();
283 assert_eq!(cursor.protected().unwrap(), &protected);
284 cursor.move_previous();
285 assert_eq!(cursor.protected(), None);
286 }
287 };
288 let check_cursor_mut = |mut cursor: crate::CursorMut<'_, _>| {
289 assert_eq!(cursor.protected().unwrap(), &protected);
290 assert_eq!(cursor.protected_mut().unwrap(), &protected);
291 assert_eq!(cursor.unprotected().unwrap(), &unprotected);
292 for _ in 0..7 {
293 cursor.move_next();
294 assert_eq!(cursor.protected(), None);
295 cursor.move_next();
296 assert_eq!(cursor.protected().unwrap(), &protected);
297 }
298 for _ in 0..10 {
299 cursor.move_previous();
300 assert_eq!(cursor.protected(), None);
301 cursor.move_previous();
302 assert_eq!(cursor.protected().unwrap(), &protected);
303 }
304 check_cursor(cursor.as_shared());
305 check_cursor(cursor.into_shared());
306 };
307
308 check_cursor(list.cursor_front());
309 check_cursor(list.cursor_back());
310 check_cursor_mut(list.cursor_front_mut());
311 check_cursor_mut(list.cursor_back_mut());
312
313 assert_eq!(
314 initialized.unlink(&mut list).unwrap(),
315 (protected, unprotected)
316 );
317
318 assert!(node.is_initial());
319 assert!(node.initialized().is_none());
320 assert!(node.as_mut().initialized_mut().is_none());
321
322 assert!(list.is_empty());
323 }
324
325 #[test]
326 fn removal() {
327 let mut list = PinList::new(id::Checked::new());
328
329 let node = crate::Node::new();
330 pin!(node);
331
332 let protected = Box::new(0);
333 let removed = Box::new(1);
334 let unprotected = Box::new(2);
335
336 let initialized_node =
337 list.push_back(node.as_mut(), protected.clone(), unprotected.clone());
338
339 assert_eq!(
340 list.cursor_front_mut()
341 .remove_current(removed.clone())
342 .unwrap(),
343 protected
344 );
345
346 assert_eq!(
347 initialized_node.take_removed(&list).unwrap(),
348 (removed, unprotected)
349 );
350 assert!(node.is_initial());
351 assert!(list.is_empty());
352 }
353
354 #[test]
355 fn removal_fallback() {
356 let mut list = PinList::new(id::Checked::new());
357
358 let node = crate::Node::new();
359 pin!(node);
360
361 let protected = Box::new(0);
362 let removed = Box::new(1);
363 let unprotected = Box::new(2);
364
365 let initialized_node =
366 list.push_front(node.as_mut(), protected.clone(), unprotected.clone());
367
368 let mut cursor = list.cursor_front_mut();
369 let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
370 cursor.remove_current_with_or(
371 |p| {
372 assert_eq!(p, protected);
373 panic::panic_any(491_u32)
374 },
375 || removed.clone(),
376 )
377 }));
378 assert_eq!(cursor.protected(), None);
379 assert_eq!(res.unwrap_err().downcast::<u32>().unwrap(), Box::new(491));
380
381 assert_eq!(
382 initialized_node.take_removed(&list).unwrap(),
383 (removed, unprotected),
384 );
385 assert!(node.is_initial());
386 assert!(list.is_empty());
387 }
388
389 #[test]
390 fn multinode() {
391 let mut list = PinList::new(id::Checked::new());
392
393 let mut nodes = (0..7)
394 .map(|_| Box::pin(crate::Node::new()))
395 .collect::<Box<[_]>>();
396
397 fn assert_order<const N: usize>(list: &mut PinList, order: [u8; N]) {
398 let mut cursor = list.cursor_ghost_mut();
400 for number in order {
401 cursor.move_next();
402 assert_eq!(**cursor.protected().unwrap(), number);
403 assert_eq!(**cursor.protected_mut().unwrap(), number);
404 assert_eq!(**cursor.unprotected().unwrap(), u32::from(number));
405 }
406 cursor.move_next();
407 assert_eq!(cursor.protected(), None);
408 assert_eq!(cursor.protected_mut(), None);
409 assert_eq!(cursor.unprotected(), None);
410
411 for number in order.into_iter().rev() {
413 cursor.move_previous();
414 assert_eq!(**cursor.protected().unwrap(), number);
415 assert_eq!(**cursor.protected_mut().unwrap(), number);
416 assert_eq!(**cursor.unprotected().unwrap(), u32::from(number));
417 }
418 cursor.move_previous();
419 assert_eq!(cursor.protected(), None);
420 assert_eq!(cursor.protected_mut(), None);
421 assert_eq!(cursor.unprotected(), None);
422 }
423
424 fn cursor(list: &mut PinList, index: usize) -> crate::CursorMut<'_, PinListTypes> {
425 let mut cursor = list.cursor_front_mut();
426 for _ in 0..index {
427 cursor.move_next();
428 cursor.protected().unwrap();
429 }
430 cursor
431 }
432
433 list.cursor_ghost_mut()
435 .insert_before(nodes[0].as_mut(), Box::new(0), Box::new(0));
436 assert_order(&mut list, [0]);
437
438 list.cursor_ghost_mut()
440 .insert_after(nodes[1].as_mut(), Box::new(1), Box::new(1));
441 assert_order(&mut list, [1, 0]);
442
443 cursor(&mut list, 0).insert_before(nodes[2].as_mut(), Box::new(2), Box::new(2));
445 assert_order(&mut list, [2, 1, 0]);
446
447 cursor(&mut list, 2).insert_after(nodes[3].as_mut(), Box::new(3), Box::new(3));
449 assert_order(&mut list, [2, 1, 0, 3]);
450
451 list.cursor_ghost_mut()
453 .insert_before(nodes[4].as_mut(), Box::new(4), Box::new(4));
454 assert_order(&mut list, [2, 1, 0, 3, 4]);
455
456 cursor(&mut list, 0).insert_after(nodes[5].as_mut(), Box::new(5), Box::new(5));
458 assert_order(&mut list, [2, 5, 1, 0, 3, 4]);
459
460 cursor(&mut list, 1).insert_before(nodes[6].as_mut(), Box::new(6), Box::new(6));
462 assert_order(&mut list, [2, 6, 5, 1, 0, 3, 4]);
463
464 fn unlink(
465 list: &mut PinList,
466 nodes: &mut [Pin<Box<crate::Node<PinListTypes>>>],
467 index: u8,
468 ) {
469 let node = nodes[usize::from(index)].as_mut();
470 let node = node.initialized_mut().expect("already unlinked");
471 let (protected, unprotected) = node.unlink(list).unwrap();
472 assert_eq!(*protected, index);
473 assert_eq!(*unprotected, u32::from(index));
474 }
475
476 fn remove(
477 list: &mut PinList,
478 nodes: &mut [Pin<Box<crate::Node<PinListTypes>>>],
479 index: u8,
480 ) {
481 let node = nodes[usize::from(index)].as_mut();
482 let node = node.initialized_mut().expect("already unlinked");
483 let mut cursor = node.cursor_mut(&mut *list).unwrap();
484 let removed = Box::new(u16::from(index));
485 assert_eq!(*cursor.remove_current(removed).unwrap(), index);
486 let (removed, unprotected) = node.take_removed(&*list).unwrap();
487 assert_eq!(*removed, u16::from(index));
488 assert_eq!(*unprotected, u32::from(index));
489 }
490
491 unlink(&mut list, &mut nodes, 6);
493 assert_order(&mut list, [2, 5, 1, 0, 3, 4]);
494
495 remove(&mut list, &mut nodes, 5);
497 assert_order(&mut list, [2, 1, 0, 3, 4]);
498
499 unlink(&mut list, &mut nodes, 4);
501 assert_order(&mut list, [2, 1, 0, 3]);
502
503 remove(&mut list, &mut nodes, 3);
505 assert_order(&mut list, [2, 1, 0]);
506
507 unlink(&mut list, &mut nodes, 2);
509 assert_order(&mut list, [1, 0]);
510
511 remove(&mut list, &mut nodes, 1);
513 assert_order(&mut list, [0]);
514
515 unlink(&mut list, &mut nodes, 0);
517 assert_order(&mut list, []);
518 }
519}