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