1macro_rules! doc_comment {
5 ($docs:expr, $($item:tt)*) => {
6 #[doc = $docs]
7 $($item)*
8 };
9}
10
11macro_rules! doc_tag_bits {
15 () => {
16 "The number of available tag bits for this type."
17 };
18}
19
20macro_rules! doc_tag_mask {
22 () => {
23 "The bitmask for the lower bits available for storing the tag value."
24 };
25}
26
27macro_rules! doc_ptr_mask {
29 () => {
30 "The bitmask for the (higher) bits for storing the pointer itself."
31 };
32}
33
34macro_rules! doc_null {
37 () => {
38 "Creates a new `null` pointer."
39 };
40}
41
42macro_rules! doc_new {
43 () => {
44 "Creates a new unmarked pointer."
45 };
46}
47
48macro_rules! doc_from_usize {
49 () => {
50 "Creates a new pointer from the numeric (integer) representation of a \
51 potentially marked pointer."
52 };
53}
54
55macro_rules! doc_into_raw {
56 () => {
57 "Returns the internal representation of the pointer *as is*, i.e. any \
58 potential tag value is **not** stripped."
59 };
60}
61
62macro_rules! doc_into_usize {
63 () => {
64 "Returns the numeric (integer) representation of the pointer with its \
65 tag value."
66 };
67}
68
69macro_rules! doc_cast {
70 () => {
71 "Casts to a pointer of another type."
72 };
73}
74
75macro_rules! doc_compose {
76 () => {
77 "Composes a new marked pointer from a raw `ptr` and a `tag` value.\n\n\
78 The supplied `ptr` is assumed to be well-aligned (i.e. has no tag bits \
79 set) and calling this function may lead to unexpected results when \
80 this is not the case."
81 };
82}
83
84macro_rules! doc_clear_tag {
85 ("non-null" $example_type_path:path) => {
86 concat!(
87 doc_clear_tag!(),
88 "# Examples\n\n\
89 ```\nuse core::ptr::NonNull;\n\n\
90 type TagNonNull = ",
91 stringify!($example_type_path),
92 ";\n\n\
93 let reference = &mut 1;\n\
94 let ptr = TagNonNull::compose(NonNull::from(reference), 0b11);\n\
95 assert_eq!(ptr.clear_tag(), TagNonNull::from(reference));\n```"
96 )
97 };
98 ($example_type_path:path) => {
99 concat!(
100 doc_clear_tag!(),
101 "# Examples\n\n\
102 ```\nuse core::ptr;\n\n\
103 type TagPtr = ",
104 stringify!($example_type_path),
105 ";\n\n\
106 let reference = &mut 1;\n\
107 let ptr = TagPtr::compose(reference, 0b11);\n\
108 assert_eq!(ptr.clear_tag(), TagPtr::new(reference));\n```"
109 )
110 };
111 () => {
112 "Clears the marked pointer's tag value.\n\n"
113 };
114}
115
116macro_rules! doc_split_tag {
117 ("non-null" $example_type_path:path) => {
118 concat!(
119 doc_split_tag!(),
120 "# Examples\n\n\
121 ```\nuse core::ptr;\n\n\
122 type TagNonNull = ",
123 stringify!($example_type_path),
124 ";\n\n\
125 let reference = &mut 1;\n\
126 let ptr = TagNonNull::compose(NonNull::from(reference), 0b11);\n\
127 assert_eq!(ptr.split_tag(), (TagNonNull::from(reference), 0b11));\n```"
128 )
129 };
130 ($example_type_path:path) => {
131 concat!(
132 doc_split_tag!(),
133 "# Examples\n\n\
134 ```\nuse core::ptr;\n\n\
135 type TagPtr = ",
136 stringify!($example_type_path),
137 ";\n\n\
138 let reference = &mut 1;\n\
139 let ptr = TagPtr::compose(reference, 0b11);\n\
140 assert_eq!(ptr.split_tag(), (TagPtr::new(reference), 0b11));\n```"
141 )
142 };
143 () => {
144 "Splits the tag value from the marked pointer, returning both the cleared pointer and the \
145 separated tag value.\n\n"
146 };
147}
148
149macro_rules! doc_set_tag {
150 ("non-null" $example_type_path:path) => {
151 concat!(
152 doc_set_tag!(),
153 "\n\n# Examples\n\n\
154 ```\nuse core::ptr;\n\n\
155 type TagNonNull = ",
156 stringify!($example_type_path),
157 ";\n\n\
158 let reference = &mut 1;\n\
159 let ptr = TagNonNull::compose(NonNull::from(reference), 0b11);\n\
160 assert_eq!(ptr.set_tag(0b10).decompose(), (NonNull::from(reference), 0b10));\n```"
161 )
162 };
163 ($example_type_path:path) => {
164 concat!(
165 doc_set_tag!(),
166 "\n\n# Examples\n\n\
167 ```\nuse core::ptr;\n\n\
168 type TagPtr = ",
169 stringify!($example_type_path),
170 ";\n\n\
171 let reference = &mut 1;\n\
172 let ptr = TagPtr::compose(reference, 0b11);\n\
173 assert_eq!(ptr.set_tag(0b10).decompose(), (reference as *mut _, 0b10));\n```"
174 )
175 };
176 () => {
177 "Sets the marked pointer's tag value to `tag` and overwrites any previous value."
178 };
179}
180
181macro_rules! doc_update_tag {
182 ("non-null" $example_type_path:path) => {
183 concat!(
184 doc_update_tag!(),
185 "\n\n# Examples\n\n\
186 ```\nuse core::ptr;\n\n\
187 type TagNonNull = ",
188 stringify!($example_type_path),
189 ";\n\n\
190 let reference = &mut 1;\n\
191 let ptr = TagNonNull::compose(reference, 0b11);\n\
192 assert_eq!(ptr.update_tag(|tag| tag - 2).decompose(), (NonNull::from(reference), 0b01));\n```"
193 )
194 };
195 ($example_type_path:path) => {
196 concat!(
197 doc_update_tag!(),
198 "\n\n# Examples\n\n\
199 ```\nuse core::ptr;\n\n\
200 type TagPtr = ",
201 stringify!($example_type_path),
202 ";\n\n\
203 let reference = &mut 1;
204 let ptr = TagPtr::compose(reference, 0b11);\n\
205 let ptr = ptr.update_tag(|tag| tag - 1);\n\
206 assert_eq!(ptr.decompose(), (reference as *mut _, 0b10));\n```"
207 )
208 };
209 () => {
210 "Updates the marked pointer's tag value to the result of `func`, which is called with the \
211 current tag value."
212 };
213}
214
215macro_rules! doc_add_tag {
216 () => {
217 "Adds `value` to the current tag *without* regard for the previous \
218 value.\n\n\
219 This method does not perform any checks so it may silently overflow \
220 the tag bits, result in a pointer to a different value, a null pointer \
221 or an unaligned pointer."
222 };
223}
224
225macro_rules! doc_sub_tag {
226 () => {
227 "Subtracts `value` from the current tag *without* regard for the \
228 previous value.\n\n\
229 This method does not perform any checks so it may silently overflow \
230 the tag bits, result in a pointer to a different value, a null \
231 pointer or an unaligned pointer."
232 };
233}
234
235macro_rules! doc_decompose {
236 () => {
237 "Decomposes the marked pointer, returning the raw pointer and the \
238 separated tag value."
239 };
240}
241
242macro_rules! doc_decompose_ptr {
243 () => {
244 "Decomposes the marked pointer, returning only the separated raw \
245 pointer."
246 };
247}
248
249macro_rules! doc_decompose_non_null {
250 () => {
251 "Decomposes the marked pointer, returning only the separated raw \
252 [`NonNull`] pointer."
253 };
254}
255
256macro_rules! doc_decompose_tag {
257 () => {
258 "Decomposes the marked pointer, returning only the separated tag value."
259 };
260}
261
262macro_rules! doc_as_ref_or_mut {
263 ("safety") => {
264 "When calling this method, you have to ensure that *either* the \
265 pointer is `null` *or* all of the following is true:\n\n\
266 - it is properly aligned\n\
267 - it must point to an initialized instance of T; in particular, \
268 the pointer must be \"de-referencable\" in the sense defined \
269 [here].\n\n\
270 This applies even if the result of this method is unused! (The \
271 part about being initialized is not yet fully decided, but until \
272 it is the only safe approach is to ensure that they are indeed \
273 initialized.)\n\n\
274 Additionally, the lifetime `'a` returned is arbitrarily chosen and \
275 does not necessarily reflect the actual lifetime of the data. \
276 *You* must enforce Rust's aliasing rules. \
277 In particular, for the duration of this lifetime, the memory this \
278 pointer points to must not get accessed (read or written) through \
279 any other pointer.\n\n\
280 [here]: [std::ptr]"
281 };
282 ($ret_str:expr) => {
283 concat!(
284 "Decomposes the marked pointer, returning ",
285 $ret_str,
286 " reference and discarding the tag value."
287 )
288 };
289}
290
291macro_rules! doc_as_ref {
292 (@inner, $ret_str:expr) => {
293 concat!(
294 doc_as_ref_or_mut!($ret_str),
295 "\n\n# Safety\n\
296 While this method and its mutable counterpart are useful for \
297 null-safety, it is important to note that this is still an unsafe \
298 operation because the returned value could be pointing to invalid \
299 memory.\n\n",
300 doc_as_ref_or_mut!("safety")
301 )
302 };
303 ("nullable") => {
304 doc_as_ref!(@inner, "an optional")
305 };
306 ("non-nullable") => {
307 doc_as_ref!(@inner, "a")
308 };
309}
310
311macro_rules! doc_as_mut {
312 (@inner, $self_ident:ident, $ret_str:expr) => {
313 concat!(
314 doc_as_ref_or_mut!($ret_str),
315 "\n\n# Safety\n\
316 As with [`as_ref`][",
317 stringify!($self_ident),
318 "::as_ref], this is unsafe because it cannot verify the validity \
319 of the returned pointer, nor can it ensure that the lifetime `'a` \
320 returned is indeed a valid lifetime for the contained data.\n\n",
321 doc_as_ref_or_mut!("safety")
322 )
323 };
324 ("nullable", $self_ident:ident) => {
325 doc_as_mut!(@inner, $self_ident, "an optional *mutable*")
326 };
327 ("non-nullable", $self_ident:ident) => {
328 doc_as_mut!(@inner, $self_ident, "a *mutable*")
329 };
330}
331
332macro_rules! doc_atomic_new {
333 () => {
334 "Creates a new atomic marked pointer."
335 };
336}
337
338macro_rules! doc_atomic_into_inner {
339 () => {
340 "Consumes the atomic marked pointer and returns its contained value.\n\n\
341 This is safe because passing `self` by value guarantees no other \
342 threads are concurrently accessing the atomic pointer."
343 };
344}