|
21 | 21 |
|
22 | 22 | #![stable(feature = "rust1", since = "1.0.0")]
|
23 | 23 |
|
24 |
| -use alloc::boxed::Box; |
| 24 | +use alloc::boxed::{Box, IntermediateBox}; |
25 | 25 | use core::cmp::Ordering;
|
26 | 26 | use core::fmt;
|
27 | 27 | use core::hash::{Hasher, Hash};
|
28 | 28 | use core::iter::FromIterator;
|
29 | 29 | use core::mem;
|
30 |
| -use core::ptr::Shared; |
| 30 | +use core::ops::{BoxPlace, InPlace, Place, Placer}; |
| 31 | +use core::ptr::{self, Shared}; |
31 | 32 |
|
32 | 33 | /// A doubly-linked list.
|
33 | 34 | #[stable(feature = "rust1", since = "1.0.0")]
|
@@ -660,6 +661,56 @@ impl<T> LinkedList<T> {
|
660 | 661 |
|
661 | 662 | second_part
|
662 | 663 | }
|
| 664 | + |
| 665 | + /// Returns a place for insertion at the front of the list. |
| 666 | + /// |
| 667 | + /// Using this method with placement syntax is equivalent to [`push_front`] |
| 668 | + /// (#method.push_front), but may be more efficient. |
| 669 | + /// |
| 670 | + /// # Examples |
| 671 | + /// |
| 672 | + /// ``` |
| 673 | + /// #![feature(collection_placement)] |
| 674 | + /// #![feature(placement_in_syntax)] |
| 675 | + /// |
| 676 | + /// use std::collections::LinkedList; |
| 677 | + /// |
| 678 | + /// let mut list = LinkedList::new(); |
| 679 | + /// list.front_place() <- 2; |
| 680 | + /// list.front_place() <- 4; |
| 681 | + /// assert!(list.iter().eq(&[4, 2])); |
| 682 | + /// ``` |
| 683 | + #[unstable(feature = "collection_placement", |
| 684 | + reason = "method name and placement protocol are subject to change", |
| 685 | + issue = "30172")] |
| 686 | + pub fn front_place(&mut self) -> FrontPlace<T> { |
| 687 | + FrontPlace { list: self, node: IntermediateBox::make_place() } |
| 688 | + } |
| 689 | + |
| 690 | + /// Returns a place for insertion at the back of the list. |
| 691 | + /// |
| 692 | + /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back), |
| 693 | + /// but may be more efficient. |
| 694 | + /// |
| 695 | + /// # Examples |
| 696 | + /// |
| 697 | + /// ``` |
| 698 | + /// #![feature(collection_placement)] |
| 699 | + /// #![feature(placement_in_syntax)] |
| 700 | + /// |
| 701 | + /// use std::collections::LinkedList; |
| 702 | + /// |
| 703 | + /// let mut list = LinkedList::new(); |
| 704 | + /// list.back_place() <- 2; |
| 705 | + /// list.back_place() <- 4; |
| 706 | + /// assert!(list.iter().eq(&[2, 4])); |
| 707 | + /// ``` |
| 708 | + #[unstable(feature = "collection_placement", |
| 709 | + reason = "method name and placement protocol are subject to change", |
| 710 | + issue = "30172")] |
| 711 | + pub fn back_place(&mut self) -> BackPlace<T> { |
| 712 | + BackPlace { list: self, node: IntermediateBox::make_place() } |
| 713 | + } |
663 | 714 | }
|
664 | 715 |
|
665 | 716 | #[stable(feature = "rust1", since = "1.0.0")]
|
@@ -984,6 +1035,101 @@ impl<A: Hash> Hash for LinkedList<A> {
|
984 | 1035 | }
|
985 | 1036 | }
|
986 | 1037 |
|
| 1038 | +unsafe fn finalize<T>(node: IntermediateBox<Node<T>>) -> Box<Node<T>> { |
| 1039 | + let mut node = node.finalize(); |
| 1040 | + ptr::write(&mut node.next, None); |
| 1041 | + ptr::write(&mut node.prev, Rawlink::none()); |
| 1042 | + node |
| 1043 | +} |
| 1044 | + |
| 1045 | +/// A place for insertion at the front of a `LinkedList`. |
| 1046 | +/// |
| 1047 | +/// See [`LinkedList::front_place`](struct.LinkedList.html#method.front_place) for details. |
| 1048 | +#[must_use = "places do nothing unless written to with `<-` syntax"] |
| 1049 | +#[unstable(feature = "collection_placement", |
| 1050 | + reason = "struct name and placement protocol are subject to change", |
| 1051 | + issue = "30172")] |
| 1052 | +pub struct FrontPlace<'a, T: 'a> { |
| 1053 | + list: &'a mut LinkedList<T>, |
| 1054 | + node: IntermediateBox<Node<T>>, |
| 1055 | +} |
| 1056 | + |
| 1057 | +#[unstable(feature = "collection_placement", |
| 1058 | + reason = "placement protocol is subject to change", |
| 1059 | + issue = "30172")] |
| 1060 | +impl<'a, T> Placer<T> for FrontPlace<'a, T> { |
| 1061 | + type Place = Self; |
| 1062 | + |
| 1063 | + fn make_place(self) -> Self { |
| 1064 | + self |
| 1065 | + } |
| 1066 | +} |
| 1067 | + |
| 1068 | +#[unstable(feature = "collection_placement", |
| 1069 | + reason = "placement protocol is subject to change", |
| 1070 | + issue = "30172")] |
| 1071 | +impl<'a, T> Place<T> for FrontPlace<'a, T> { |
| 1072 | + fn pointer(&mut self) -> *mut T { |
| 1073 | + unsafe { &mut (*self.node.pointer()).value } |
| 1074 | + } |
| 1075 | +} |
| 1076 | + |
| 1077 | +#[unstable(feature = "collection_placement", |
| 1078 | + reason = "placement protocol is subject to change", |
| 1079 | + issue = "30172")] |
| 1080 | +impl<'a, T> InPlace<T> for FrontPlace<'a, T> { |
| 1081 | + type Owner = (); |
| 1082 | + |
| 1083 | + unsafe fn finalize(self) { |
| 1084 | + let FrontPlace { list, node } = self; |
| 1085 | + list.push_front_node(finalize(node)); |
| 1086 | + } |
| 1087 | +} |
| 1088 | + |
| 1089 | +/// A place for insertion at the back of a `LinkedList`. |
| 1090 | +/// |
| 1091 | +/// See [`LinkedList::back_place`](struct.LinkedList.html#method.back_place) for details. |
| 1092 | +#[must_use = "places do nothing unless written to with `<-` syntax"] |
| 1093 | +#[unstable(feature = "collection_placement", |
| 1094 | + reason = "struct name and placement protocol are subject to change", |
| 1095 | + issue = "30172")] |
| 1096 | +pub struct BackPlace<'a, T: 'a> { |
| 1097 | + list: &'a mut LinkedList<T>, |
| 1098 | + node: IntermediateBox<Node<T>>, |
| 1099 | +} |
| 1100 | + |
| 1101 | +#[unstable(feature = "collection_placement", |
| 1102 | + reason = "placement protocol is subject to change", |
| 1103 | + issue = "30172")] |
| 1104 | +impl<'a, T> Placer<T> for BackPlace<'a, T> { |
| 1105 | + type Place = Self; |
| 1106 | + |
| 1107 | + fn make_place(self) -> Self { |
| 1108 | + self |
| 1109 | + } |
| 1110 | +} |
| 1111 | + |
| 1112 | +#[unstable(feature = "collection_placement", |
| 1113 | + reason = "placement protocol is subject to change", |
| 1114 | + issue = "30172")] |
| 1115 | +impl<'a, T> Place<T> for BackPlace<'a, T> { |
| 1116 | + fn pointer(&mut self) -> *mut T { |
| 1117 | + unsafe { &mut (*self.node.pointer()).value } |
| 1118 | + } |
| 1119 | +} |
| 1120 | + |
| 1121 | +#[unstable(feature = "collection_placement", |
| 1122 | + reason = "placement protocol is subject to change", |
| 1123 | + issue = "30172")] |
| 1124 | +impl<'a, T> InPlace<T> for BackPlace<'a, T> { |
| 1125 | + type Owner = (); |
| 1126 | + |
| 1127 | + unsafe fn finalize(self) { |
| 1128 | + let BackPlace { list, node } = self; |
| 1129 | + list.push_back_node(finalize(node)); |
| 1130 | + } |
| 1131 | +} |
| 1132 | + |
987 | 1133 | // Ensure that `LinkedList` and its read-only iterators are covariant in their type parameters.
|
988 | 1134 | #[allow(dead_code)]
|
989 | 1135 | fn assert_covariance() {
|
|
0 commit comments