Skip to content

Commit 9c16e31

Browse files
committed
Generate ArrayVecCopy without using patch
Invent this little hack, insert directives like this in ArrayVec: ```rust // DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)] ``` And replace them as follows in ArrayVecCopy: ```rust \#[cfg(not_in_arrayvec_copy)] ```
1 parent 6a182a2 commit 9c16e31

File tree

5 files changed

+81
-98
lines changed

5 files changed

+81
-98
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,7 @@ features = ["borsh", "serde", "zeroize"]
6060
[package.metadata.release]
6161
no-dev-version = true
6262
tag-name = "{{version}}"
63+
64+
65+
[lints.rust]
66+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(not_in_arrayvec_copy)'] }

generate_arrayvec_copy

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ set -o errexit
33
set -o nounset
44
set -o pipefail
55

6+
# Generate ArrayVecCopy from ArrayVec
7+
# Replace type name with ArrayVecCopy
8+
# Insert `T: Copy` bound as needed.
9+
#
10+
# Replace `// DIRECTIVE ArrayVecCopy` with empty string anywhere to allow
11+
# items to be cfg'ed out for arrayvec copy
12+
613
sed \
714
-e "s/\\<ArrayVec\\>/ArrayVecCopy/g" \
815
-e "s/\\<ArrayVecVisitor\\>/ArrayVecCopyVisitor/g" \
@@ -13,25 +20,8 @@ sed \
1320
-e "s/fn \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T:/fn \\1<\\2T: Copy +/g" \
1421
-e "s/fn \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T,/fn \\1<\\2T: Copy,/g" \
1522
-e "s/const fn/fn/" \
23+
-e "s/\\/\\/ DIRECTIVE ArrayVecCopy \\+//" \
1624
src/arrayvec.rs \
1725
> src/arrayvec_copy_generated.rs
1826

19-
trap "rm src/arrayvec_copy_generated.rs" EXIT
20-
21-
if [ -e src/arrayvec_copy.patch ]; then
22-
if [ -e src/arrayvec_copy.rs ]; then
23-
echo "Both src/arrayvec_copy.patch and src/arrayvec_copy.rs exist." > /dev/stderr
24-
echo "Delete one of them and start again." > /dev/stderr
25-
exit 1
26-
else
27-
patch -o src/arrayvec_copy.rs src/arrayvec_copy_generated.rs src/arrayvec_copy.patch > /dev/null
28-
fi
29-
else
30-
if [ -e src/arrayvec_copy.rs ]; then
31-
git diff --no-index src/arrayvec_copy_generated.rs src/arrayvec_copy.rs > src/arrayvec_copy.patch || true
32-
else
33-
echo "Both src/arrayvec_copy.patch and src/arrayvec_copy.rs are missing." > /dev/stderr
34-
echo "One of them is needed to generate the other." > /dev/stderr
35-
exit 1
36-
fi
37-
fi
27+
mv -v -f src/arrayvec_copy_generated.rs src/arrayvec_copy.rs

src/arrayvec.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
// The ArrayVec and ArrayVecCopy implementation
2+
//
3+
// NOTE: arrayvec.rs is the original source of both arrayvec.rs and arrayvec_copy.rs.
4+
// NOTE: Do not modify arrayvec_copy.rs manually. It is generated using the script
5+
// ./generate_arrayvec_copy.
6+
//
7+
// Any lines marked with a comment and then `DIRECTIVE ArrayVecCopy` will have that prefix removed
8+
// and have the rest of the line active in the ArrayVecCopy implementation.
19

210
use std::cmp;
311
use std::iter;
@@ -23,6 +31,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
2331
use crate::LenUint;
2432
use crate::errors::CapacityError;
2533
use crate::arrayvec_impl::ArrayVecImpl;
34+
// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
2635
use crate::utils::MakeMaybeUninit;
2736

2837
/// A vector with a fixed capacity.
@@ -39,13 +48,17 @@ use crate::utils::MakeMaybeUninit;
3948
///
4049
/// It offers a simple API but also dereferences to a slice, so that the full slice API is
4150
/// available. The ArrayVec can be converted into a by value iterator.
51+
// DIRECTIVE ArrayVecCopy #[doc = ""]
52+
// DIRECTIVE ArrayVecCopy #[doc = "**ArrayVecCopy's only difference to [`\x41rrayVec`](crate::\x41rrayVec) is that its"]
53+
// DIRECTIVE ArrayVecCopy #[doc = "elements are constrained to be `Copy` which allows it to be `Copy` itself.** "]
4254
#[repr(C)]
4355
pub struct ArrayVec<T, const CAP: usize> {
4456
len: LenUint,
4557
// the `len` first elements of the array are initialized
4658
xs: [MaybeUninit<T>; CAP],
4759
}
4860

61+
// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
4962
impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> {
5063
fn drop(&mut self) {
5164
self.clear();
@@ -87,6 +100,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
87100
}
88101
}
89102

103+
// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
90104
/// Create a new empty `ArrayVec` (const fn).
91105
///
92106
/// The maximum capacity is given by the generic parameter `CAP`.
@@ -964,6 +978,7 @@ impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {
964978

965979
impl<T, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { }
966980

981+
// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
967982
impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
968983
fn drop(&mut self) {
969984
// panic safety: Set length to 0 before dropping elements.

src/arrayvec_copy.patch

Lines changed: 0 additions & 76 deletions
This file was deleted.

src/arrayvec_copy.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
// The ArrayVecCopy and ArrayVecCopy implementation
2+
//
3+
// NOTE: arrayvec.rs is the original source of both arrayvec.rs and arrayvec_copy.rs.
4+
// NOTE: Do not modify arrayvec_copy.rs manually. It is generated using the script
5+
// ./generate_arrayvec_copy.
6+
//
7+
// Any lines marked with a comment and then `DIRECTIVE ArrayVecCopy` will have that prefix removed
8+
// and have the rest of the line active in the ArrayVecCopy implementation.
19

210
use std::cmp;
311
use std::iter;
@@ -23,12 +31,11 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
2331
use crate::LenUint;
2432
use crate::errors::CapacityError;
2533
use crate::arrayvec_impl::ArrayVecImpl;
34+
#[cfg(not_in_arrayvec_copy)]
35+
use crate::utils::MakeMaybeUninit;
2636

2737
/// A vector with a fixed capacity.
2838
///
29-
/// **Its only difference to [`ArrayVec`](crate::ArrayVec) is that its elements
30-
/// are constrained to be `Copy` which allows it to be `Copy` itself.**
31-
///
3239
/// The `ArrayVecCopy` is a vector backed by a fixed size array. It keeps track of
3340
/// the number of initialized elements. The `ArrayVecCopy<T, CAP>` is parameterized
3441
/// by `T` for the element type and `CAP` for the maximum capacity.
@@ -41,13 +48,25 @@ use crate::arrayvec_impl::ArrayVecImpl;
4148
///
4249
/// It offers a simple API but also dereferences to a slice, so that the full slice API is
4350
/// available. The ArrayVecCopy can be converted into a by value iterator.
51+
#[doc = ""]
52+
#[doc = "**ArrayVecCopy's only difference to [`\x41rrayVec`](crate::\x41rrayVec) is that its"]
53+
#[doc = "elements are constrained to be `Copy` which allows it to be `Copy` itself.** "]
4454
#[repr(C)]
4555
pub struct ArrayVecCopy<T: Copy, const CAP: usize> {
4656
len: LenUint,
4757
// the `len` first elements of the array are initialized
4858
xs: [MaybeUninit<T>; CAP],
4959
}
5060

61+
#[cfg(not_in_arrayvec_copy)]
62+
impl<T: Copy, const CAP: usize> Drop for ArrayVecCopy<T, CAP> {
63+
fn drop(&mut self) {
64+
self.clear();
65+
66+
// MaybeUninit inhibits array's drop
67+
}
68+
}
69+
5170
macro_rules! panic_oob {
5271
($method_name:expr, $index:expr, $len:expr) => {
5372
panic!(concat!("ArrayVecCopy::", $method_name, ": index {} is out of bounds in vector of length {}"),
@@ -81,6 +100,21 @@ impl<T: Copy, const CAP: usize> ArrayVecCopy<T, CAP> {
81100
}
82101
}
83102

103+
#[cfg(not_in_arrayvec_copy)]
104+
/// Create a new empty `ArrayVecCopy` (fn).
105+
///
106+
/// The maximum capacity is given by the generic parameter `CAP`.
107+
///
108+
/// ```
109+
/// use arrayvec::ArrayVecCopy;
110+
///
111+
/// static ARRAY: ArrayVecCopy<u8, 1024> = ArrayVecCopy::new_const();
112+
/// ```
113+
pub fn new_const() -> ArrayVecCopy<T, CAP> {
114+
assert_capacity_limit_const!(CAP);
115+
ArrayVecCopy { xs: MakeMaybeUninit::ARRAY, len: 0 }
116+
}
117+
84118
/// Return the number of elements in the `ArrayVecCopy`.
85119
///
86120
/// ```
@@ -944,6 +978,22 @@ impl<T: Copy, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {
944978

945979
impl<T: Copy, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { }
946980

981+
#[cfg(not_in_arrayvec_copy)]
982+
impl<T: Copy, const CAP: usize> Drop for IntoIter<T, CAP> {
983+
fn drop(&mut self) {
984+
// panic safety: Set length to 0 before dropping elements.
985+
let index = self.index;
986+
let len = self.v.len();
987+
unsafe {
988+
self.v.set_len(0);
989+
let elements = slice::from_raw_parts_mut(
990+
self.v.get_unchecked_ptr(index),
991+
len - index);
992+
ptr::drop_in_place(elements);
993+
}
994+
}
995+
}
996+
947997
impl<T: Copy, const CAP: usize> Clone for IntoIter<T, CAP>
948998
where T: Clone,
949999
{

0 commit comments

Comments
 (0)