1 | use core::ptr; |
2 | |
3 | use super::{IsZero, Vec}; |
4 | use crate::alloc::Allocator; |
5 | use crate::raw_vec::RawVec; |
6 | |
7 | // Specialization trait used for Vec::from_elem |
8 | pub(super) trait SpecFromElem: Sized { |
9 | fn from_elem<A: Allocator>(elem: Self, n: usize, alloc: A) -> Vec<Self, A>; |
10 | } |
11 | |
12 | impl<T: Clone> SpecFromElem for T { |
13 | #[track_caller ] |
14 | default fn from_elem<A: Allocator>(elem: Self, n: usize, alloc: A) -> Vec<Self, A> { |
15 | let mut v: Vec = Vec::with_capacity_in(capacity:n, alloc); |
16 | v.extend_with(n, value:elem); |
17 | v |
18 | } |
19 | } |
20 | |
21 | impl<T: Clone + IsZero> SpecFromElem for T { |
22 | #[inline ] |
23 | #[track_caller ] |
24 | default fn from_elem<A: Allocator>(elem: T, n: usize, alloc: A) -> Vec<T, A> { |
25 | if elem.is_zero() { |
26 | return Vec { buf: RawVec::with_capacity_zeroed_in(capacity:n, alloc), len: n }; |
27 | } |
28 | let mut v: Vec = Vec::with_capacity_in(capacity:n, alloc); |
29 | v.extend_with(n, value:elem); |
30 | v |
31 | } |
32 | } |
33 | |
34 | impl SpecFromElem for i8 { |
35 | #[inline ] |
36 | #[track_caller ] |
37 | fn from_elem<A: Allocator>(elem: i8, n: usize, alloc: A) -> Vec<i8, A> { |
38 | if elem == 0 { |
39 | return Vec { buf: RawVec::with_capacity_zeroed_in(capacity:n, alloc), len: n }; |
40 | } |
41 | let mut v: Vec = Vec::with_capacity_in(capacity:n, alloc); |
42 | unsafe { |
43 | ptr::write_bytes(dst:v.as_mut_ptr(), val:elem as u8, count:n); |
44 | v.set_len(new_len:n); |
45 | } |
46 | v |
47 | } |
48 | } |
49 | |
50 | impl SpecFromElem for u8 { |
51 | #[inline ] |
52 | #[track_caller ] |
53 | fn from_elem<A: Allocator>(elem: u8, n: usize, alloc: A) -> Vec<u8, A> { |
54 | if elem == 0 { |
55 | return Vec { buf: RawVec::with_capacity_zeroed_in(capacity:n, alloc), len: n }; |
56 | } |
57 | let mut v: Vec = Vec::with_capacity_in(capacity:n, alloc); |
58 | unsafe { |
59 | ptr::write_bytes(dst:v.as_mut_ptr(), val:elem, count:n); |
60 | v.set_len(new_len:n); |
61 | } |
62 | v |
63 | } |
64 | } |
65 | |
66 | // A better way would be to implement this for all ZSTs which are `Copy` and have trivial `Clone` |
67 | // but the latter cannot be detected currently |
68 | impl SpecFromElem for () { |
69 | #[inline ] |
70 | fn from_elem<A: Allocator>(_elem: (), n: usize, alloc: A) -> Vec<(), A> { |
71 | let mut v: Vec<(), A> = Vec::with_capacity_in(capacity:n, alloc); |
72 | // SAFETY: the capacity has just been set to `n` |
73 | // and `()` is a ZST with trivial `Clone` implementation |
74 | unsafe { |
75 | v.set_len(new_len:n); |
76 | } |
77 | v |
78 | } |
79 | } |
80 | |