satsnet_internals/
array_vec.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! A simplified `Copy` version of `arrayvec::ArrayVec`.
4
5use core::fmt;
6
7pub use safety_boundary::ArrayVec;
8
9/// Limits the scope of `unsafe` auditing.
10// New trait impls and fns that don't need to access internals should go below the module, not
11// inside it!
12mod safety_boundary {
13    use core::mem::MaybeUninit;
14
15    use crate::const_tools::cond_const;
16
17    /// A growable contiguous collection backed by array.
18    #[derive(Copy)]
19    pub struct ArrayVec<T: Copy, const CAP: usize> {
20        len: usize,
21        data: [MaybeUninit<T>; CAP],
22    }
23
24    impl<T: Copy, const CAP: usize> ArrayVec<T, CAP> {
25        // The bounds are const-unstable until 1.61
26        cond_const! {
27            /// Creates an empty `ArrayVec`.
28            pub const(in rust_v_1_61 = "1.61") fn new() -> Self {
29                Self {
30                    len: 0,
31                    data: [MaybeUninit::uninit(); CAP],
32                }
33            }
34
35            /// Creates an `ArrayVec` initialized with the contets of `slice`.
36            ///
37            /// # Panics
38            ///
39            /// If the slice is longer than `CAP`.
40            pub const(in rust_v_1_61 = "1.61") fn from_slice(slice: &[T]) -> Self {
41                assert!(slice.len() <= CAP);
42                let mut data = [MaybeUninit::uninit(); CAP];
43                let mut i = 0;
44                // can't use mutable references and operators in const
45                while i < slice.len() {
46                    data[i] = MaybeUninit::new(slice[i]);
47                    i += 1;
48                }
49
50                Self {
51                    len: slice.len(),
52                    data,
53                }
54            }
55        }
56
57        // from_raw_parts is const-unstable until 1.64
58        cond_const! {
59            /// Returns a reference to the underlying data.
60            pub const(in rust_v_1_64 = "1.64") fn as_slice(&self) -> &[T] {
61                let ptr = &self.data as *const _ as *const T;
62                unsafe { core::slice::from_raw_parts(ptr, self.len) }
63            }
64        }
65
66        /// Returns a mutable reference to the underlying data.
67        pub fn as_mut_slice(&mut self) -> &mut [T] {
68            unsafe { &mut *(&mut self.data[..self.len] as *mut _ as *mut [T]) }
69        }
70
71        /// Adds an element into `self`.
72        ///
73        /// # Panics
74        ///
75        /// If the length would increase past CAP.
76        pub fn push(&mut self, element: T) {
77            assert!(self.len < CAP);
78            self.data[self.len] = MaybeUninit::new(element);
79            self.len += 1;
80        }
81
82        /// Copies and appends all elements from `slice` into `self`.
83        ///
84        /// # Panics
85        ///
86        /// If the length would increase past CAP.
87        pub fn extend_from_slice(&mut self, slice: &[T]) {
88            let new_len = self
89                .len
90                .checked_add(slice.len())
91                .expect("integer/buffer overflow");
92            assert!(new_len <= CAP, "buffer overflow");
93            // SAFETY: MaybeUninit<T> has the same layout as T
94            let slice = unsafe { &*(slice as *const _ as *const [MaybeUninit<T>]) };
95            self.data[self.len..].copy_from_slice(slice);
96            self.len = new_len;
97        }
98    }
99}
100
101impl<T: Copy, const CAP: usize> Default for ArrayVec<T, CAP> {
102    fn default() -> Self {
103        Self::new()
104    }
105}
106
107/// Clones the value *faster* than using `Copy`.
108///
109/// Because we avoid copying the uninitialized part of the array this copies the value faster than
110/// memcpy.
111#[allow(clippy::non_canonical_clone_impl)]
112impl<T: Copy, const CAP: usize> Clone for ArrayVec<T, CAP> {
113    fn clone(&self) -> Self {
114        Self::from_slice(self)
115    }
116}
117
118impl<T: Copy, const CAP: usize> core::ops::Deref for ArrayVec<T, CAP> {
119    type Target = [T];
120
121    fn deref(&self) -> &Self::Target {
122        self.as_slice()
123    }
124}
125
126impl<T: Copy, const CAP: usize> core::ops::DerefMut for ArrayVec<T, CAP> {
127    fn deref_mut(&mut self) -> &mut Self::Target {
128        self.as_mut_slice()
129    }
130}
131
132impl<T: Copy + Eq, const CAP: usize> Eq for ArrayVec<T, CAP> {}
133
134impl<T: Copy + PartialEq, const CAP1: usize, const CAP2: usize> PartialEq<ArrayVec<T, CAP2>>
135    for ArrayVec<T, CAP1>
136{
137    fn eq(&self, other: &ArrayVec<T, CAP2>) -> bool {
138        **self == **other
139    }
140}
141
142impl<T: Copy + PartialEq, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP> {
143    fn eq(&self, other: &[T]) -> bool {
144        **self == *other
145    }
146}
147
148impl<T: Copy + PartialEq, const CAP: usize> PartialEq<ArrayVec<T, CAP>> for [T] {
149    fn eq(&self, other: &ArrayVec<T, CAP>) -> bool {
150        *self == **other
151    }
152}
153
154impl<T: Copy + PartialEq, const CAP: usize, const LEN: usize> PartialEq<[T; LEN]>
155    for ArrayVec<T, CAP>
156{
157    fn eq(&self, other: &[T; LEN]) -> bool {
158        **self == *other
159    }
160}
161
162impl<T: Copy + PartialEq, const CAP: usize, const LEN: usize> PartialEq<ArrayVec<T, CAP>>
163    for [T; LEN]
164{
165    fn eq(&self, other: &ArrayVec<T, CAP>) -> bool {
166        *self == **other
167    }
168}
169
170impl<T: Copy + Ord, const CAP: usize> Ord for ArrayVec<T, CAP> {
171    fn cmp(&self, other: &ArrayVec<T, CAP>) -> core::cmp::Ordering {
172        (**self).cmp(&**other)
173    }
174}
175
176impl<T: Copy + PartialOrd, const CAP1: usize, const CAP2: usize> PartialOrd<ArrayVec<T, CAP2>>
177    for ArrayVec<T, CAP1>
178{
179    fn partial_cmp(&self, other: &ArrayVec<T, CAP2>) -> Option<core::cmp::Ordering> {
180        (**self).partial_cmp(&**other)
181    }
182}
183
184impl<T: Copy + fmt::Debug, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> {
185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186        fmt::Debug::fmt(&**self, f)
187    }
188}
189
190impl<T: Copy + core::hash::Hash, const CAP: usize> core::hash::Hash for ArrayVec<T, CAP> {
191    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
192        core::hash::Hash::hash(&**self, state)
193    }
194}