tagged_pointer/reference/implied.rs
1/*
2 * Copyright 2023-2024 Jonáš Fiala <jonas.fiala@inf.ethz.ch>
3 * Copyright 2023-2024 taylor.fish <contact@taylor.fish>
4 *
5 * This file is part of tagged-pointer.
6 *
7 * tagged-pointer is licensed under the Apache License, Version 2.0
8 * (the "License"); you may not use tagged-pointer except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20use crate::implied::TaggedPtr;
21use core::marker::PhantomData;
22
23macro_rules! impl_implied_tagged_ref_common {
24 ($name:ident $(,)?) => {
25 impl<T> $name<'_, T> {
26 /// The number of tag bits that this tagged reference can store.
27 /// Equal to <code>[align_of]::\<T>().[trailing_zeros]\()</code>
28 /// (because alignment is always a power of 2, this is the base-2
29 /// logarithm of the alignment of `T`).
30 ///
31 /// [align_of]: core::mem::align_of
32 /// [trailing_zeros]: usize::trailing_zeros
33 pub const BITS: u32 = TaggedPtr::<T>::BITS;
34
35 /// The maximum tag (inclusive) that this tagged reference can
36 /// store. Equal to <code>[align_of]::\<T>() - 1</code>.
37 ///
38 /// [align_of]: core::mem::align_of
39 pub const MAX_TAG: usize = TaggedPtr::<T>::MAX_TAG;
40 }
41 };
42}
43
44/// A tagged reference with the maximum tag size for the given type.
45///
46/// This type behaves like [`crate::TaggedRef`] but doesn't have a `BITS`
47/// parameter that determines how many tag bits to store. Instead, this type
48/// uses the largest possible tag size for a reference to `T`; see
49/// [`Self::BITS`] for the exact calculation.
50#[repr(transparent)]
51pub struct TaggedRef<'a, T>(TaggedPtr<T>, PhantomData<&'a T>);
52
53impl<'a, T> TaggedRef<'a, T> {
54 /// Creates a new tagged reference. Only the lower [`Self::BITS`] bits of
55 /// `tag` are stored.
56 pub fn new(reference: &'a T, tag: usize) -> Self {
57 Self::new_impl(reference, tag)
58 }
59}
60
61impl_implied_tagged_ref_common!(TaggedRef);
62impl_tagged_ref_common!([T], [T], "# use tagged_pointer::implied::TaggedRef;");
63
64/// Mutable version of [`TaggedRef`].
65///
66/// This type behaves like [`crate::TaggedMutRef`] but doesn't have a `BITS`
67/// parameter that determines how many tag bits to store. Instead, this type
68/// uses the largest possible tag size for a reference to `T`; see
69/// [`Self::BITS`] for the exact calculation.
70#[repr(transparent)]
71pub struct TaggedMutRef<'a, T>(TaggedPtr<T>, PhantomData<&'a mut T>);
72
73impl<'a, T> TaggedMutRef<'a, T> {
74 /// Creates a new tagged mutable reference. Only the lower [`Self::BITS`]
75 /// bits of `tag` are stored.
76 pub fn new(reference: &'a mut T, tag: usize) -> Self {
77 Self::new_impl(reference, tag)
78 }
79}
80
81impl_implied_tagged_ref_common!(TaggedMutRef);
82impl_tagged_mut_ref_common!(
83 [T],
84 [T],
85 "# use tagged_pointer::implied::TaggedMutRef;",
86);