mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 04:57:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			70 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| #[cfg(test)]
 | |
| mod tests;
 | |
| 
 | |
| /// Uses a sorted slice `data: &[E]` as a kind of "multi-map". The
 | |
| /// `key_fn` extracts a key of type `K` from the data, and this
 | |
| /// function finds the range of elements that match the key. `data`
 | |
| /// must have been sorted as if by a call to `sort_by_key` for this to
 | |
| /// work.
 | |
| pub fn binary_search_slice<E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, key: &K) -> &'d [E]
 | |
| where
 | |
|     K: Ord,
 | |
| {
 | |
|     let mid = match data.binary_search_by_key(key, &key_fn) {
 | |
|         Ok(mid) => mid,
 | |
|         Err(_) => return &[],
 | |
|     };
 | |
|     let size = data.len();
 | |
| 
 | |
|     // We get back *some* element with the given key -- so do
 | |
|     // a galloping search backwards to find the *first* one.
 | |
|     let mut start = mid;
 | |
|     let mut previous = mid;
 | |
|     let mut step = 1;
 | |
|     loop {
 | |
|         start = start.saturating_sub(step);
 | |
|         if start == 0 || key_fn(&data[start]) != *key {
 | |
|             break;
 | |
|         }
 | |
|         previous = start;
 | |
|         step *= 2;
 | |
|     }
 | |
|     step = previous - start;
 | |
|     while step > 1 {
 | |
|         let half = step / 2;
 | |
|         let mid = start + half;
 | |
|         if key_fn(&data[mid]) != *key {
 | |
|             start = mid;
 | |
|         }
 | |
|         step -= half;
 | |
|     }
 | |
|     // adjust by one if we have overshot
 | |
|     if start < size && key_fn(&data[start]) != *key {
 | |
|         start += 1;
 | |
|     }
 | |
| 
 | |
|     // Now search forward to find the *last* one.
 | |
|     let mut end = mid;
 | |
|     let mut previous = mid;
 | |
|     let mut step = 1;
 | |
|     loop {
 | |
|         end = end.saturating_add(step).min(size);
 | |
|         if end == size || key_fn(&data[end]) != *key {
 | |
|             break;
 | |
|         }
 | |
|         previous = end;
 | |
|         step *= 2;
 | |
|     }
 | |
|     step = end - previous;
 | |
|     while step > 1 {
 | |
|         let half = step / 2;
 | |
|         let mid = end - half;
 | |
|         if key_fn(&data[mid]) != *key {
 | |
|             end = mid;
 | |
|         }
 | |
|         step -= half;
 | |
|     }
 | |
| 
 | |
|     &data[start..end]
 | |
| }
 | 
