mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 20:44:34 +00:00 
			
		
		
		
	 4457014398
			
		
	
	
		4457014398
		
	
	
	
	
		
			
			The PR had some unforseen perf regressions that are not as easy to find. Revert the PR for now. This reverts commit 6ae8912a3e7d2c4c775024f58a7ba4b1aedc4073, reversing changes made to 86d6d2b7389fe1b339402c1798edae8b695fc9ef.
		
			
				
	
	
		
			82 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //! A singly-linked list.
 | |
| //!
 | |
| //! Using this data structure only makes sense under very specific
 | |
| //! circumstances:
 | |
| //!
 | |
| //! - If you have a list that rarely stores more than one element, then this
 | |
| //!   data-structure can store the element without allocating and only uses as
 | |
| //!   much space as an `Option<(T, usize)>`. If T can double as the `Option`
 | |
| //!   discriminant, it will even only be as large as `T, usize`.
 | |
| //!
 | |
| //! If you expect to store more than 1 element in the common case, steer clear
 | |
| //! and use a `Vec<T>`, `Box<[T]>`, or a `SmallVec<T>`.
 | |
| 
 | |
| #[cfg(test)]
 | |
| mod tests;
 | |
| 
 | |
| #[derive(Clone)]
 | |
| pub struct TinyList<T> {
 | |
|     head: Option<Element<T>>,
 | |
| }
 | |
| 
 | |
| impl<T: PartialEq> TinyList<T> {
 | |
|     #[inline]
 | |
|     pub fn new() -> TinyList<T> {
 | |
|         TinyList { head: None }
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     pub fn new_single(data: T) -> TinyList<T> {
 | |
|         TinyList { head: Some(Element { data, next: None }) }
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     pub fn insert(&mut self, data: T) {
 | |
|         self.head = Some(Element { data, next: self.head.take().map(Box::new) });
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     pub fn remove(&mut self, data: &T) -> bool {
 | |
|         self.head = match self.head {
 | |
|             Some(ref mut head) if head.data == *data => head.next.take().map(|x| *x),
 | |
|             Some(ref mut head) => return head.remove_next(data),
 | |
|             None => return false,
 | |
|         };
 | |
|         true
 | |
|     }
 | |
| 
 | |
|     #[inline]
 | |
|     pub fn contains(&self, data: &T) -> bool {
 | |
|         let mut elem = self.head.as_ref();
 | |
|         while let Some(ref e) = elem {
 | |
|             if &e.data == data {
 | |
|                 return true;
 | |
|             }
 | |
|             elem = e.next.as_deref();
 | |
|         }
 | |
|         false
 | |
|     }
 | |
| }
 | |
| 
 | |
| #[derive(Clone)]
 | |
| struct Element<T> {
 | |
|     data: T,
 | |
|     next: Option<Box<Element<T>>>,
 | |
| }
 | |
| 
 | |
| impl<T: PartialEq> Element<T> {
 | |
|     fn remove_next(&mut self, data: &T) -> bool {
 | |
|         let mut n = self;
 | |
|         loop {
 | |
|             match n.next {
 | |
|                 Some(ref mut next) if next.data == *data => {
 | |
|                     n.next = next.next.take();
 | |
|                     return true;
 | |
|                 }
 | |
|                 Some(ref mut next) => n = next,
 | |
|                 None => return false,
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |