diff --git a/src/lib.rs b/src/lib.rs index 8df8147..6538e74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,8 +38,6 @@ //! Creating a list, appending nodes, and printing them out: //! //! ``` -//! extern crate indexlist; -//! //! use indexlist::IndexList; //! //! let mut list = IndexList::new(); @@ -57,8 +55,6 @@ //! Removing an item from the list: //! //! ``` -//! extern crate indexlist; -//! //! use indexlist::IndexList; //! //! let mut list = IndexList::new(); @@ -75,8 +71,6 @@ //! Generational indexes: //! //! ``` -//! extern crate indexlist; -//! //! use indexlist::IndexList; //! //! let mut list = IndexList::new(); @@ -147,8 +141,6 @@ struct OccupiedEntry { /// You can get an `Index` by inserting something into the list: /// /// ``` -/// extern crate indexlist; -/// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -160,8 +152,6 @@ struct OccupiedEntry { /// You can also get one with `index_of`: /// /// ``` -/// extern crate indexlist; -/// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -213,8 +203,6 @@ where /// Making a new list: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let list: IndexList = IndexList::new(); @@ -234,8 +222,6 @@ where /// Making a new list: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let list: IndexList = IndexList::with_capacity(100); @@ -259,8 +245,6 @@ where /// The first item is often the first one that's pushed on: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -273,8 +257,6 @@ where /// But of course, not always! /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -304,8 +286,6 @@ where /// The first item is often the first one that's pushed on: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -318,8 +298,6 @@ where /// But of course, not always! /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -365,8 +343,6 @@ where /// Pushing several numbers into a list: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -478,8 +454,6 @@ where /// Pushing several numbers into a list: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -562,8 +536,6 @@ where /// Checking both possibilities: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -595,8 +567,6 @@ where /// Getting an element at an index: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -609,8 +579,6 @@ where /// An element that doesn't exist returns `None`: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -625,8 +593,6 @@ where /// Generational indexes ensure that we don't access incorrect items: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -664,8 +630,6 @@ where /// Getting an element at an index: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -678,8 +642,6 @@ where /// An element that doesn't exist returns `None`: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -694,8 +656,6 @@ where /// Generational indexes ensure that we don't access incorrect items: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -763,8 +723,6 @@ where /// Removing an element from an index: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -780,8 +738,6 @@ where /// An element that doesn't exist returns `None`: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -796,8 +752,6 @@ where /// Generational indexes ensure that we don't access incorrect items: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -907,6 +861,146 @@ where } } + /// Inserts an element immediately before the provided index. Returns `None` + /// if the element at the provided index was removed. + /// + /// # Example + /// + /// ``` + /// use indexlist::IndexList; + /// + /// let mut list = IndexList::new(); + /// + /// let five = list.push_back(5); + /// list.insert_before(five, 0); + /// + /// assert_eq!(list.head(), Some(&0)); + /// ``` + pub fn insert_before(&mut self, index: Index, item: T) -> Option> { + // Get the current index + let (prev_index, index, _next_index) = match self.contents.get(index.index)? { + Entry::Free { .. } => return None, + Entry::Occupied(e) => { + // are we of the right generation? + if index.generation != e.generation { + return None; + } + (e.prev, index.index, e.next) + } + }; + let entry = Entry::Occupied(OccupiedEntry { + item, + generation: self.generation, + next: Some(index), + prev: prev_index, + }); + // Insert the item + let position = if let Some(position) = self.next_free { + // update next_free + match self.contents[position] { + Entry::Occupied { .. } => panic!("Corrupted list"), + Entry::Free { next_free } => self.next_free = next_free, + } + self.contents[position] = entry; + position + } else { + // we don't have any, so append to the end of the list + let position = self.contents.len(); + self.contents.push(entry); + position + }; + match &mut self.contents[index] { + Entry::Free { .. } => panic!("Corrupted list"), + Entry::Occupied(e) => { + e.prev = Some(position); + } + } + // Now, we need to update the prev node, if there was one, as well as + // the head, if there wasn't + match prev_index { + Some(index) => match &mut self.contents[index] { + Entry::Occupied(e) => { + e.next = Some(position); + } + _ => panic!("Corrupted list"), + }, + None => { + self.head = Some(position); + } + } + Some(Index::new(position, self.generation)) + } + + /// Inserts an element immediately after the provided index. Returns `None` + /// if the element at the provided index was removed. + /// + /// # Example + /// + /// ``` + /// use indexlist::IndexList; + /// + /// let mut list = IndexList::new(); + /// + /// let five = list.push_back(5); + /// list.insert_after(five, 0); + /// + /// assert_eq!(list.tail_index().and_then(|tail| list.get(tail)), Some(&0)); + /// ``` + pub fn insert_after(&mut self, index: Index, item: T) -> Option> { + // Get the current index + let (_prev_index, index, next_index) = match self.contents.get(index.index)? { + Entry::Free { .. } => return None, + Entry::Occupied(e) => { + // are we of the right generation? + if index.generation != e.generation { + return None; + } + (e.prev, index.index, e.next) + } + }; + let entry = Entry::Occupied(OccupiedEntry { + item, + generation: self.generation, + next: next_index, + prev: Some(index), + }); + // Insert the item + let position = if let Some(position) = self.next_free { + // update next_free + match self.contents[position] { + Entry::Occupied { .. } => panic!("Corrupted list"), + Entry::Free { next_free } => self.next_free = next_free, + } + self.contents[position] = entry; + position + } else { + // we don't have any, so append to the end of the list + let position = self.contents.len(); + self.contents.push(entry); + position + }; + match &mut self.contents[index] { + Entry::Free { .. } => panic!("Corrupted list"), + Entry::Occupied(e) => { + e.next = Some(position); + } + } + // Now, we need to update the prev node, if there was one, as well as + // the head, if there wasn't + match next_index { + Some(index) => match &mut self.contents[index] { + Entry::Occupied(e) => { + e.prev = Some(position); + } + _ => panic!("Corrupted list"), + }, + None => { + self.tail = Some(position); + } + } + Some(Index::new(position, self.generation)) + } + /// Returns an iterator of references to the items in the list. /// /// # Examples @@ -914,8 +1008,6 @@ where /// Using an iterator to print out all of the items in a list: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -945,8 +1037,6 @@ where /// Finding an item: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -989,8 +1079,6 @@ where /// Removing the head: /// /// ``` - /// extern crate indexlist; - /// /// use indexlist::IndexList; /// /// let mut list = IndexList::new(); @@ -1843,4 +1931,36 @@ mod tests { } ); } + + #[test] + fn insert_before() { + let mut list = IndexList::new(); + + let index = list.push_front(2); + list.insert_before(index, 0); + + assert_eq!(list.iter().copied().collect::>(), vec![0, 2]); + assert_eq!(*list.get(list.prev_index(index).unwrap()).unwrap(), 0); + + list.insert_before(index, 1); + + assert_eq!(list.iter().copied().collect::>(), vec![0, 1, 2]); + assert_eq!(*list.get(list.prev_index(index).unwrap()).unwrap(), 1); + } + + #[test] + fn insert_after() { + let mut list = IndexList::new(); + + let index = list.push_front(0); + list.insert_after(index, 2); + + assert_eq!(list.iter().copied().collect::>(), vec![0, 2]); + assert_eq!(*list.get(list.next_index(index).unwrap()).unwrap(), 2); + + list.insert_after(index, 1); + + assert_eq!(list.iter().copied().collect::>(), vec![0, 1, 2]); + assert_eq!(*list.get(list.next_index(index).unwrap()).unwrap(), 1); + } }