1use crate::alloc::AllocError;
4use crate::sealed::Sealed;
5use std::alloc::{Allocator, Global};
6
7pub trait VecAllocExt<T, A: Allocator>: Sized + Sealed {
9 fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, AllocError>;
10 fn try_push(&mut self, value: T) -> Result<(), AllocError>;
11 fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), AllocError>
12 where
13 T: Copy;
14 fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), AllocError>
15 where
16 F: FnMut() -> T;
17 fn try_copy_from_slice(&mut self, other: &[T]) -> Result<(), AllocError>
18 where
19 T: Copy;
20}
21
22pub trait VecExt<T>: VecAllocExt<T, Global> {
24 fn try_with_capacity(capacity: usize) -> Result<Self, AllocError>;
25}
26
27impl<T, A: Allocator> Sealed for Vec<T, A> {}
28
29impl<T, A: Allocator> VecAllocExt<T, A> for Vec<T, A> {
30 #[inline]
31 fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, AllocError> {
32 let mut vec = Vec::new_in(alloc);
33 vec.try_reserve(capacity)?;
34 Ok(vec)
35 }
36
37 #[inline]
38 fn try_push(&mut self, value: T) -> Result<(), AllocError> {
39 if self.len() == self.capacity() {
40 self.try_reserve(1)?;
41 }
42 self.push(value);
43 Ok(())
44 }
45
46 #[inline]
47 fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), AllocError>
48 where
49 T: Copy,
50 {
51 if new_len > self.len() {
52 self.try_reserve(new_len - self.len())?;
53 }
54 self.resize(new_len, value);
55 Ok(())
56 }
57
58 #[inline]
59 fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), AllocError>
60 where
61 F: FnMut() -> T,
62 {
63 if new_len > self.len() {
64 self.try_reserve(new_len - self.len())?;
65 }
66 self.resize_with(new_len, f);
67 Ok(())
68 }
69
70 fn try_copy_from_slice(&mut self, other: &[T]) -> Result<(), AllocError>
71 where
72 T: Copy,
73 {
74 self.try_reserve(other.len())?;
75 self.extend_from_slice(other);
76 Ok(())
77 }
78}
79
80impl<T> VecExt<T> for Vec<T> {
81 #[inline]
82 fn try_with_capacity(capacity: usize) -> Result<Self, AllocError> {
83 let mut vec = Vec::new();
84 vec.try_reserve(capacity)?;
85 Ok(vec)
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use std::alloc::{AllocError, Layout};
93 use std::ptr::NonNull;
94
95 struct Alloc {
96 inner: Global,
97 _mark: u64,
98 }
99
100 impl Alloc {
101 pub const fn new() -> Self {
102 Alloc {
103 inner: Global,
104 _mark: u64::MAX,
105 }
106 }
107 }
108
109 unsafe impl Allocator for Alloc {
110 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
111 self.inner.allocate(layout)
112 }
113
114 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
115 self.inner.deallocate(ptr, layout)
116 }
117 }
118
119 #[test]
120 fn test_vec() {
121 let mut v = Vec::try_with_capacity(1).unwrap();
122 v.try_push(1).unwrap();
123 v.try_push(2).unwrap();
124 v.try_push(3).unwrap();
125 assert_eq!(v, [1, 2, 3]);
126 }
127
128 #[test]
129 fn test_vec_with_alloc() {
130 let mut v = Vec::try_with_capacity_in(1, Alloc::new()).unwrap();
131 v.try_push(1).unwrap();
132 v.try_push(2).unwrap();
133 v.try_push(3).unwrap();
134 assert_eq!(v, [1, 2, 3]);
135 }
136
137 #[test]
138 fn test_vec_resize() {
139 let mut v = Vec::new_in(Alloc::new());
140 v.try_resize(3, 1).unwrap();
141 assert_eq!(v, [1, 1, 1]);
142 }
143
144 #[test]
145 fn test_vec_resize_with() {
146 let mut v = Vec::new_in(Alloc::new());
147 let mut i = 0;
148 v.try_resize_with(3, || {
149 i += 1;
150 i
151 })
152 .unwrap();
153 assert_eq!(v, [1, 2, 3]);
154 }
155
156 #[test]
157 fn test_vec_extend_from_slice() {
158 let mut v = Vec::new_in(Alloc::new());
159 v.try_copy_from_slice(&[1, 2, 3]).unwrap();
160 assert_eq!(v, [1, 2, 3]);
161 }
162}