tagptr/macros/
doc.rs

1/// All macros for generating documentation.
2
3/// A macro for generating arbitrary documented code items
4macro_rules! doc_comment {
5    ($docs:expr, $($item:tt)*) => {
6        #[doc = $docs]
7        $($item)*
8    };
9}
10
11/********** macros for generating constants docs **************************************************/
12
13/// A macro for generating the docs for the `TAG_BITS` constant.
14macro_rules! doc_tag_bits {
15    () => {
16        "The number of available tag bits for this type."
17    };
18}
19
20/// A macro for generating the docs for the `TAG_MASK` constant.
21macro_rules! doc_tag_mask {
22    () => {
23        "The bitmask for the lower bits available for storing the tag value."
24    };
25}
26
27/// A macro for generating the docs for the `PTR_MASK` constants.
28macro_rules! doc_ptr_mask {
29    () => {
30        "The bitmask for the (higher) bits for storing the pointer itself."
31    };
32}
33
34/********** macros for generating function docs ***************************************************/
35
36macro_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}