1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Defines `BaseArrayPtr`, the interface `BaseArray` uses when defining methods.
/// Trait representing an unsafe reference to an array.
///
/// Should be the same size as the underlying pointer.
///
/// # Implementing this Type
/// Let `a` be an instance of `A`, which is a concrete implementation of
/// `BaseArrayPtr<E, L>`. The following must hold on `a`:
///
/// - `a.dealloc(len)` is safe to call on the result of `A::alloc(len)`
/// - `a.elem_ptr(idx)` and `a.lbl_ptr()` must return properly aligned pointers
/// for the types `E` and `L` respectively
/// - `a.lbl_ptr()` must return the same value for the lifetime
/// of `a` for all `let a = A::alloc(len)`, or at least until `a.dealloc()`
/// is called.
/// - `a.elem_ptr(idx)` must return the same value for each value of `idx` for the
/// lifetime of `a` for all `let a = A::alloc(len)`, or at least until `a.dealloc()`
/// is called.
/// - `A::alloc(len).elem_ptr(idx)` returns a pointer to allocated memory for all
/// `idx < len`
/// - The difference in addresses between `a.elem_ptr(idx + 1)` and `a.elem_ptr(idx)`
/// is exactly `core::mem::size_of::<E>()`; i.e. the objects that `a.elem_ptr`
/// points to are in an array
/// - `A::alloc(len).lbl_ptr()` returns a pointer to allocated memory
/// - `a._init()` is safe to call on the result of `A::alloc(len)`
/// - `a._drop()` is safe to call on any result of `A::alloc(len)` for which
/// `_init()` has been called exactly once
/// - `A::from_ptr(A::alloc(len).as_ptr())` is safe; i.e. `A::from_ptr` and
/// `A::as_ptr` must agree on the raw pointer representation of `A`
///
/// # Use of API by `BaseArray`
/// Let `A` be a concrete implementation of `BaseArrayPtr`. At initialization via
/// `BaseArray::new`, `BaseArray::new_lazy`, or `BaseArray::alloc`, `BaseArray`
/// does the following:
///
/// 1. Call `A::alloc(len)`
/// 2. Call `a._init()` on the newly created instance
/// 3. Optionally call constructor methods (depending on which method)
/// 1. Label is initialized first by calling `a.lbl_ptr()` and writing to it
/// 2. Elements are initialized by calling `a.elem_ptr(idx)` and writing to it
/// for each `idx < len`
///
/// At destruction via `BaseArray::drop` or `BaseArray::drop_lazy`, `BaseArray`
/// does the following:
///
/// 1. Optionally call destructors (depending on which method)
/// 1. Label is destructed first, in place
/// 2. Elements are destructed in ascending order
/// 2. Call `a._drop()`
/// 3. Call `a.dealloc()`
///
/// On accessing an element, `BaseArray` calls `elem_ptr`, and on accessing the
/// label, `BaseArray` calls `lbl_ptr`
pub unsafe