Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Copy to ArrayVec enabled by a feature #192

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ harness = false
[features]
default = ["std"]
std = []
copy = []

[profile.bench]
debug = true
Expand Down
63 changes: 37 additions & 26 deletions src/arrayvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
use crate::LenUint;
use crate::errors::CapacityError;
use crate::arrayvec_impl::ArrayVecImpl;
#[cfg(not(feature="copy"))]
use crate::utils::MakeMaybeUninit;

/// A vector with a fixed capacity.
Expand All @@ -45,6 +46,12 @@ pub struct ArrayVec<T, const CAP: usize> {
len: LenUint,
}

// Safety: when the `copy` feature is enabled the only way
// to construct an `ArrayVec` is if `T: Copy`.
#[cfg(feature="copy")]
impl<T: Copy, const CAP: usize> Copy for ArrayVec<T, CAP> {}

#[cfg(not(feature="copy"))]
impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> {
fn drop(&mut self) {
self.clear();
Expand All @@ -60,10 +67,8 @@ macro_rules! panic_oob {
}
}

impl<T, const CAP: usize> ArrayVec<T, CAP> {
/// Capacity
const CAPACITY: usize = CAP;

// creating function:
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> ArrayVec<T, CAP> {
/// Create a new empty `ArrayVec`.
///
/// The maximum capacity is given by the generic parameter `CAP`.
Expand Down Expand Up @@ -93,11 +98,30 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
///
/// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const();
/// ```
#[cfg(not(feature="copy"))]
pub const fn new_const() -> ArrayVec<T, CAP> {
assert_capacity_limit_const!(CAP);
ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 }
}

/// Returns the ArrayVec, replacing the original with a new empty ArrayVec.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut v = ArrayVec::from([0, 1, 2, 3]);
/// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap());
/// assert!(v.is_empty());
/// ```
pub fn take(&mut self) -> Self {
mem::replace(self, Self::new())
}
}

impl<T, const CAP: usize> ArrayVec<T, CAP> {
/// Capacity
const CAPACITY: usize = CAP;

/// Return the number of elements in the `ArrayVec`.
///
/// ```
Expand Down Expand Up @@ -651,19 +675,6 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
array
}

/// Returns the ArrayVec, replacing the original with a new empty ArrayVec.
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut v = ArrayVec::from([0, 1, 2, 3]);
/// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap());
/// assert!(v.is_empty());
/// ```
pub fn take(&mut self) -> Self {
mem::replace(self, Self::new())
}

/// Return a slice containing all elements of the vector.
pub fn as_slice(&self) -> &[T] {
ArrayVecImpl::as_slice(self)
Expand Down Expand Up @@ -730,7 +741,7 @@ impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> {
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 3);
/// ```
impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
fn from(array: [T; CAP]) -> Self {
let array = ManuallyDrop::new(array);
let mut vec = <ArrayVec<T, CAP>>::new();
Expand All @@ -755,7 +766,7 @@ impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 4);
/// ```
impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP>
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP>
where T: Clone,
{
type Error = CapacityError;
Expand Down Expand Up @@ -884,7 +895,7 @@ impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
}
}

impl<T, const CAP: usize> Clone for IntoIter<T, CAP>
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> Clone for IntoIter<T, CAP>
where T: Clone,
{
fn clone(&self) -> IntoIter<T, CAP> {
Expand Down Expand Up @@ -1074,7 +1085,7 @@ unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T {
/// Create an `ArrayVec` from an iterator.
///
/// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
/// Create an `ArrayVec` from an iterator.
///
/// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
Expand All @@ -1085,7 +1096,7 @@ impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
}
}

impl<T, const CAP: usize> Clone for ArrayVec<T, CAP>
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> Clone for ArrayVec<T, CAP>
where T: Clone
{
fn clone(&self) -> Self {
Expand Down Expand Up @@ -1153,7 +1164,7 @@ impl<T, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> where T: fmt::Debug {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
}

impl<T, const CAP: usize> Default for ArrayVec<T, CAP> {
impl<#[cfg(feature="copy")] T: Copy, #[cfg(not(feature="copy"))] T, const CAP: usize> Default for ArrayVec<T, CAP> {
/// Return an empty array
fn default() -> ArrayVec<T, CAP> {
ArrayVec::new()
Expand Down Expand Up @@ -1214,16 +1225,16 @@ impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> {

#[cfg(feature="serde")]
/// Requires crate feature `"serde"`
impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> {
impl<'de, #[cfg(feature="copy")] T: Copy + Deserialize<'de>, #[cfg(not(feature="copy"))] T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
use serde::de::{Visitor, SeqAccess, Error};
use std::marker::PhantomData;

struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);
struct ArrayVecVisitor<'de, #[cfg(feature="copy")] T: Copy + Deserialize<'de>, #[cfg(not(feature="copy"))] T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);

impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> {
impl<'de, #[cfg(feature="copy")] T: Copy + Deserialize<'de>, #[cfg(not(feature="copy"))] T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> {
type Value = ArrayVec<T, CAP>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Expand Down
13 changes: 13 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::collections::HashMap;


#[test]
#[cfg(not(feature="copy"))]
fn test_simple() {
use std::ops::Add;

Expand Down Expand Up @@ -97,6 +98,7 @@ fn test_iter() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_drop() {
use std::cell::Cell;

Expand Down Expand Up @@ -189,6 +191,7 @@ fn test_drop() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_drop_panics() {
use std::cell::Cell;
use std::panic::catch_unwind;
Expand Down Expand Up @@ -299,6 +302,7 @@ fn test_extend_capacity_panic_2() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_is_send_sync() {
let data = ArrayVec::<Vec<i32>, 5>::new();
&data as &dyn Send;
Expand Down Expand Up @@ -398,6 +402,7 @@ fn test_drain_oob() {

#[test]
#[should_panic]
#[cfg(not(feature="copy"))]
fn test_drop_panic() {
struct DropPanic;

Expand All @@ -413,6 +418,7 @@ fn test_drop_panic() {

#[test]
#[should_panic]
#[cfg(not(feature="copy"))]
fn test_drop_panic_into_iter() {
struct DropPanic;

Expand Down Expand Up @@ -460,6 +466,7 @@ fn test_into_inner_1() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_into_inner_2() {
let mut v = ArrayVec::<String, 4>::new();
v.push("a".into());
Expand Down Expand Up @@ -498,6 +505,7 @@ fn test_write() {
}

#[test]
#[cfg(not(feature="copy"))]
fn array_clone_from() {
let mut v = ArrayVec::<_, 4>::new();
v.push(vec![1, 2]);
Expand Down Expand Up @@ -633,6 +641,7 @@ fn test_insert_out_of_bounds() {
*/

#[test]
#[cfg(not(feature="copy"))]
fn test_drop_in_insert() {
use std::cell::Cell;

Expand Down Expand Up @@ -664,6 +673,7 @@ fn test_drop_in_insert() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_pop_at() {
let mut v = ArrayVec::<String, 4>::new();
let s = String::from;
Expand All @@ -686,6 +696,7 @@ fn test_sizes() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_default() {
use std::net;
let s: ArrayString<4> = Default::default();
Expand Down Expand Up @@ -754,6 +765,7 @@ fn deny_max_capacity_arrayvec_value() {

#[should_panic(expected="index out of bounds")]
#[test]
#[cfg(not(feature="copy"))]
fn deny_max_capacity_arrayvec_value_const() {
if mem::size_of::<usize>() <= mem::size_of::<u32>() {
panic!("This test does not work on this platform. 'index out of bounds'");
Expand All @@ -763,6 +775,7 @@ fn deny_max_capacity_arrayvec_value_const() {
}

#[test]
#[cfg(not(feature="copy"))]
fn test_arrayvec_const_constructible() {
const OF_U8: ArrayVec<Vec<u8>, 10> = ArrayVec::new_const();

Expand Down