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);