Skip to content

Commit d9222c0

Browse files
authored
Merge pull request #101 from Thomasdezeeuw/extend_from_slice
Add ArrayVec.extend_from_slice and capacity_left
2 parents d84cb37 + 8a8332f commit d9222c0

File tree

3 files changed

+86
-11
lines changed

3 files changed

+86
-11
lines changed

benches/extend.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,16 @@ fn extend_with_slice(b: &mut Bencher) {
4040
b.bytes = v.capacity() as u64;
4141
}
4242

43-
benchmark_group!(benches, extend_with_constant, extend_with_range, extend_with_slice);
43+
fn extend_with_slice_fn(b: &mut Bencher) {
44+
let mut v = ArrayVec::<[u8; 512]>::new();
45+
let data = [1; 512];
46+
b.iter(|| {
47+
v.clear();
48+
black_box(v.extend_from_slice(&data));
49+
v[0]
50+
});
51+
b.bytes = v.capacity() as u64;
52+
}
53+
54+
benchmark_group!(benches, extend_with_constant, extend_with_range, extend_with_slice, extend_with_slice_fn);
4455
benchmark_main!(benches);

src/lib.rs

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,19 @@ impl<A: Array> ArrayVec<A> {
172172
/// ```
173173
pub fn is_full(&self) -> bool { self.len() == self.capacity() }
174174

175+
/// Returns the capacity left in the `ArrayVec`.
176+
///
177+
/// ```
178+
/// use arrayvec::ArrayVec;
179+
///
180+
/// let mut array = ArrayVec::from([1, 2, 3]);
181+
/// array.pop();
182+
/// assert_eq!(array.capacity_left(), 1);
183+
/// ```
184+
pub fn capacity_left(&self) -> usize {
185+
self.capacity() - self.len()
186+
}
187+
175188
/// Push `element` to the end of the vector.
176189
///
177190
/// ***Panics*** if the vector is already full.
@@ -523,6 +536,39 @@ impl<A: Array> ArrayVec<A> {
523536
self.len = Index::from(length);
524537
}
525538

539+
/// Copy and appends all elements in a slice to the `ArrayVec`.
540+
///
541+
/// ```
542+
/// use arrayvec::ArrayVec;
543+
///
544+
/// let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new();
545+
/// vec.push(1);
546+
/// vec.extend_from_slice(&[2, 3]);
547+
/// assert_eq!(&vec[..], &[1, 2, 3]);
548+
/// ```
549+
///
550+
/// # Panics
551+
///
552+
/// This method will panic if the capacity left (see [`capacity_left`]) is
553+
/// smaller then the length of the provided slice.
554+
///
555+
/// [`capacity_left`]: #method.capacity_left
556+
pub fn extend_from_slice(&mut self, other: &[A::Item])
557+
where A::Item: Copy,
558+
{
559+
if self.capacity_left() < other.len() {
560+
panic!("ArrayVec::extend_from_slice: slice is larger then capacity left");
561+
}
562+
563+
let self_len = self.len();
564+
let other_len = other.len();
565+
566+
unsafe {
567+
let dst = self.xs.as_mut_ptr().offset(self_len as isize);
568+
ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len);
569+
self.set_len(self_len + other_len);
570+
}
571+
}
526572

527573
/// Create a draining iterator that removes the specified range in the vector
528574
/// and yields the removed items from start to end. The element range is
@@ -1033,16 +1079,9 @@ impl<A: Array> Ord for ArrayVec<A> where A::Item: Ord {
10331079
/// Requires `features="std"`.
10341080
impl<A: Array<Item=u8>> io::Write for ArrayVec<A> {
10351081
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1036-
unsafe {
1037-
let len = self.len();
1038-
let mut tail = slice::from_raw_parts_mut(self.get_unchecked_mut(len),
1039-
A::capacity() - len);
1040-
let result = tail.write(data);
1041-
if let Ok(written) = result {
1042-
self.set_len(len + written);
1043-
}
1044-
result
1045-
}
1082+
let len = cmp::min(self.capacity_left(), data.len());
1083+
self.extend_from_slice(&data[..len]);
1084+
Ok(len)
10461085
}
10471086
fn flush(&mut self) -> io::Result<()> { Ok(()) }
10481087
}

tests/tests.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@ fn test_simple() {
2727
assert_eq!(sum_len, 8);
2828
}
2929

30+
#[test]
31+
fn test_capacity_left() {
32+
let mut vec: ArrayVec<[usize; 4]> = ArrayVec::new();
33+
assert_eq!(vec.capacity_left(), 4);
34+
vec.push(1);
35+
assert_eq!(vec.capacity_left(), 3);
36+
vec.push(2);
37+
assert_eq!(vec.capacity_left(), 2);
38+
vec.push(3);
39+
assert_eq!(vec.capacity_left(), 1);
40+
vec.push(4);
41+
assert_eq!(vec.capacity_left(), 0);
42+
}
43+
44+
#[test]
45+
fn test_extend_from_slice() {
46+
let mut vec: ArrayVec<[usize; 10]> = ArrayVec::new();
47+
48+
vec.extend_from_slice(&[1, 2, 3]);
49+
assert_eq!(vec.len(), 3);
50+
assert_eq!(&vec[..], &[1, 2, 3]);
51+
assert_eq!(vec.pop(), Some(3));
52+
assert_eq!(&vec[..], &[1, 2]);
53+
}
54+
3055
#[test]
3156
fn test_u16_index() {
3257
const N: usize = 4096;

0 commit comments

Comments
 (0)