about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-09 17:36:48 +0000
committerbors <bors@rust-lang.org>2023-05-09 17:36:48 +0000
commitb7cdd93f3e1533e96d4cfa1ac8573e6210a2bedf (patch)
treee893f9a927eb64e163db90e91939dda0953b92a4
parentc26a43d6bd660eba94500645a47f931e153015d8 (diff)
parentadd94d3b9ca53921796ad1336aa67701b6cf888a (diff)
downloadrust-b7cdd93f3e1533e96d4cfa1ac8573e6210a2bedf.tar.gz
rust-b7cdd93f3e1533e96d4cfa1ac8573e6210a2bedf.zip
Auto merge of #14747 - oxalica:feat/arena-idx-range, r=HKalbasi
More APIs for `la_arena::IdxRange`

```rust
impl<T> ExactSizeIterator for IdxRange<T>;

impl<T> Arena<T> {
    pub fn alloc_many<II: IntoIterator<Item = T>>(&mut self, iter: II) -> IdxRange<T>;
}
```

1. There are no currently ways to get `IdxRange` without manually offseting `Idx`. Providing a method for multiple-allocation simplifies this process and makes it less error-prone.
2. `IdxRange: ExactSizeIterator` makes `iter.zip(range).rev()` possible. Since `Zip: DoubleEndedIterator` requires all its arguments to be `ExactSizeIterator`. It also ease the usage for, eg. `len()`.
3. Fixed a typo.

I noticed that `IdxRange::end` may be invalid. Is it good to return `Idx` instead of `RawIdx`?
-rw-r--r--lib/la-arena/src/lib.rs46
1 files changed, 44 insertions, 2 deletions
diff --git a/lib/la-arena/src/lib.rs b/lib/la-arena/src/lib.rs
index b03fa5b61d3..1f8ef01a5bc 100644
--- a/lib/la-arena/src/lib.rs
+++ b/lib/la-arena/src/lib.rs
@@ -6,7 +6,7 @@
 use std::{
     cmp, fmt,
     hash::{Hash, Hasher},
-    iter::Enumerate,
+    iter::{Enumerate, FusedIterator},
     marker::PhantomData,
     ops::{Index, IndexMut, Range, RangeInclusive},
 };
@@ -168,7 +168,7 @@ impl<T> IdxRange<T> {
         Idx::from_raw(RawIdx::from(self.range.start))
     }
 
-    /// Returns the start of the index range.
+    /// Returns the end of the index range.
     pub fn end(&self) -> Idx<T> {
         Idx::from_raw(RawIdx::from(self.range.end))
     }
@@ -176,9 +176,32 @@ impl<T> IdxRange<T> {
 
 impl<T> Iterator for IdxRange<T> {
     type Item = Idx<T>;
+
     fn next(&mut self) -> Option<Self::Item> {
         self.range.next().map(|raw| Idx::from_raw(raw.into()))
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.range.size_hint()
+    }
+
+    fn count(self) -> usize
+    where
+        Self: Sized,
+    {
+        self.range.count()
+    }
+
+    fn last(self) -> Option<Self::Item>
+    where
+        Self: Sized,
+    {
+        self.range.last().map(|raw| Idx::from_raw(raw.into()))
+    }
+
+    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+        self.range.nth(n).map(|raw| Idx::from_raw(raw.into()))
+    }
 }
 
 impl<T> DoubleEndedIterator for IdxRange<T> {
@@ -187,6 +210,10 @@ impl<T> DoubleEndedIterator for IdxRange<T> {
     }
 }
 
+impl<T> ExactSizeIterator for IdxRange<T> {}
+
+impl<T> FusedIterator for IdxRange<T> {}
+
 impl<T> fmt::Debug for IdxRange<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_tuple(&format!("IdxRange::<{}>", std::any::type_name::<T>()))
@@ -305,6 +332,21 @@ impl<T> Arena<T> {
         idx
     }
 
+    /// Densely allocates multiple values, returning the values’ index range.
+    ///
+    /// ```
+    /// let mut arena = la_arena::Arena::new();
+    /// let range = arena.alloc_many(0..4);
+    ///
+    /// assert_eq!(arena[range], [0, 1, 2, 3]);
+    /// ```
+    pub fn alloc_many<II: IntoIterator<Item = T>>(&mut self, iter: II) -> IdxRange<T> {
+        let start = self.next_idx();
+        self.extend(iter);
+        let end = self.next_idx();
+        IdxRange::new(start..end)
+    }
+
     /// Returns an iterator over the arena’s elements.
     ///
     /// ```