Skip to content

Generate ArrayVecCopy without using patch #2

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

Merged
merged 2 commits into from
Oct 21, 2024
Merged
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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ features = ["borsh", "serde", "zeroize"]
[package.metadata.release]
no-dev-version = true
tag-name = "{{version}}"


[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(not_in_arrayvec_copy)'] }
29 changes: 9 additions & 20 deletions generate_arrayvec_copy
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,24 @@ set -o errexit
set -o nounset
set -o pipefail

# Generate ArrayVecCopy from ArrayVec
# Replace type name with ArrayVecCopy
# Insert `T: Copy` bound as needed.
#
# Replace `// DIRECTIVE ArrayVecCopy` with empty string anywhere to allow
# items to be cfg'ed out for arrayvec copy

sed \
-e "s/\\<ArrayVec\\>/ArrayVecCopy/g" \
-e "s/\\<ArrayVecVisitor\\>/ArrayVecCopyVisitor/g" \
-e "s/impl<\\('[A-Za-z_]*, \\)\\?T:/impl<\\1T: Copy +/g" \
-e "s/impl<\\('[A-Za-z_]*, \\)\\?T,/impl<\\1T: Copy,/g" \
-e "s/struct \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T:/struct \\1<\\2T: Copy +/g" \
-e "s/struct \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T,/struct \\1<\\2T: Copy,/g" \
-e "s/fn \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T:/fn \\1<\\2T: Copy +/g" \
-e "s/fn \\([A-Za-z_]*\\)<\\('[A-Za-z_]*, \\)\\?T,/fn \\1<\\2T: Copy,/g" \
-e "s/const fn/fn/" \
-e "s/\\/\\/ DIRECTIVE ArrayVecCopy \\+//" \
src/arrayvec.rs \
> src/arrayvec_copy_generated.rs

trap "rm src/arrayvec_copy_generated.rs" EXIT

if [ -e src/arrayvec_copy.patch ]; then
if [ -e src/arrayvec_copy.rs ]; then
echo "Both src/arrayvec_copy.patch and src/arrayvec_copy.rs exist." > /dev/stderr
echo "Delete one of them and start again." > /dev/stderr
exit 1
else
patch -o src/arrayvec_copy.rs src/arrayvec_copy_generated.rs src/arrayvec_copy.patch > /dev/null
fi
else
if [ -e src/arrayvec_copy.rs ]; then
git diff --no-index src/arrayvec_copy_generated.rs src/arrayvec_copy.rs > src/arrayvec_copy.patch || true
else
echo "Both src/arrayvec_copy.patch and src/arrayvec_copy.rs are missing." > /dev/stderr
echo "One of them is needed to generate the other." > /dev/stderr
exit 1
fi
fi
mv -v -f src/arrayvec_copy_generated.rs src/arrayvec_copy.rs
15 changes: 15 additions & 0 deletions src/arrayvec.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
// The ArrayVec and ArrayVecCopy implementation
//
// NOTE: arrayvec.rs is the original source of both arrayvec.rs and arrayvec_copy.rs.
// NOTE: Do not modify arrayvec_copy.rs manually. It is generated using the script
// ./generate_arrayvec_copy.
//
// Any lines marked with a comment and then `DIRECTIVE ArrayVecCopy` will have that prefix removed
// and have the rest of the line active in the ArrayVecCopy implementation.

use std::cmp;
use std::iter;
Expand All @@ -23,6 +31,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
use crate::LenUint;
use crate::errors::CapacityError;
use crate::arrayvec_impl::ArrayVecImpl;
// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
use crate::utils::MakeMaybeUninit;

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

// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> {
fn drop(&mut self) {
self.clear();
Expand Down Expand Up @@ -87,6 +100,7 @@ impl<T, const CAP: usize> ArrayVec<T, CAP> {
}
}

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

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

// DIRECTIVE ArrayVecCopy #[cfg(not_in_arrayvec_copy)]
impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
fn drop(&mut self) {
// panic safety: Set length to 0 before dropping elements.
Expand Down
76 changes: 0 additions & 76 deletions src/arrayvec_copy.patch

This file was deleted.

62 changes: 56 additions & 6 deletions src/arrayvec_copy.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
// The ArrayVecCopy and ArrayVecCopy implementation
//
// NOTE: arrayvec.rs is the original source of both arrayvec.rs and arrayvec_copy.rs.
// NOTE: Do not modify arrayvec_copy.rs manually. It is generated using the script
// ./generate_arrayvec_copy.
//
// Any lines marked with a comment and then `DIRECTIVE ArrayVecCopy` will have that prefix removed
// and have the rest of the line active in the ArrayVecCopy implementation.

use std::cmp;
use std::iter;
Expand All @@ -23,12 +31,11 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer};
use crate::LenUint;
use crate::errors::CapacityError;
use crate::arrayvec_impl::ArrayVecImpl;
#[cfg(not_in_arrayvec_copy)]
use crate::utils::MakeMaybeUninit;

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

#[cfg(not_in_arrayvec_copy)]
impl<T: Copy, const CAP: usize> Drop for ArrayVecCopy<T, CAP> {
fn drop(&mut self) {
self.clear();

// MaybeUninit inhibits array's drop
}
}

macro_rules! panic_oob {
($method_name:expr, $index:expr, $len:expr) => {
panic!(concat!("ArrayVecCopy::", $method_name, ": index {} is out of bounds in vector of length {}"),
Expand Down Expand Up @@ -81,6 +100,21 @@ impl<T: Copy, const CAP: usize> ArrayVecCopy<T, CAP> {
}
}

#[cfg(not_in_arrayvec_copy)]
/// Create a new empty `ArrayVecCopy` (fn).
///
/// The maximum capacity is given by the generic parameter `CAP`.
///
/// ```
/// use arrayvec::ArrayVecCopy;
///
/// static ARRAY: ArrayVecCopy<u8, 1024> = ArrayVecCopy::new_const();
/// ```
pub fn new_const() -> ArrayVecCopy<T, CAP> {
assert_capacity_limit_const!(CAP);
ArrayVecCopy { xs: MakeMaybeUninit::ARRAY, len: 0 }
}

/// Return the number of elements in the `ArrayVecCopy`.
///
/// ```
Expand Down Expand Up @@ -944,6 +978,22 @@ impl<T: Copy, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {

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

#[cfg(not_in_arrayvec_copy)]
impl<T: Copy, const CAP: usize> Drop for IntoIter<T, CAP> {
fn drop(&mut self) {
// panic safety: Set length to 0 before dropping elements.
let index = self.index;
let len = self.v.len();
unsafe {
self.v.set_len(0);
let elements = slice::from_raw_parts_mut(
self.v.get_unchecked_ptr(index),
len - index);
ptr::drop_in_place(elements);
}
}
}

impl<T: Copy, const CAP: usize> Clone for IntoIter<T, CAP>
where T: Clone,
{
Expand Down Expand Up @@ -1285,9 +1335,9 @@ impl<'de, T: Copy + Deserialize<'de>, const CAP: usize> Deserialize<'de> for Arr
use serde::de::{Visitor, SeqAccess, Error};
use std::marker::PhantomData;

struct ArrayVecCopyVisitor<'de, T: Copy + Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);
struct ArrayVecVisitor<'de, T: Copy + Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);

impl<'de, T: Copy + Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecCopyVisitor<'de, T, CAP> {
impl<'de, T: Copy + Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> {
type Value = ArrayVecCopy<T, CAP>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
Expand All @@ -1309,7 +1359,7 @@ impl<'de, T: Copy + Deserialize<'de>, const CAP: usize> Deserialize<'de> for Arr
}
}

deserializer.deserialize_seq(ArrayVecCopyVisitor::<T, CAP>(PhantomData))
deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP>(PhantomData))
}
}

Expand Down