foyer_common/bits.rs
1// Copyright 2025 foyer Project Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Copyright 2023 RisingWave Labs
16//
17// Licensed under the Apache License, Version 2.0 (the "License");
18// you may not use this file except in compliance with the License.
19// You may obtain a copy of the License at
20//
21// http://www.apache.org/licenses/LICENSE-2.0
22//
23// Unless required by applicable law or agreed to in writing, software
24// distributed under the License is distributed on an "AS IS" BASIS,
25// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
26// See the License for the specific language governing permissions and
27// limitations under the License.
28
29use std::{
30 fmt::{Debug, Display},
31 ops::{Add, BitAnd, Not, Sub},
32};
33
34/// An unsigned trait that used by the utils.
35pub trait Unsigned:
36 Add<Output = Self>
37 + Sub<Output = Self>
38 + BitAnd<Output = Self>
39 + Not<Output = Self>
40 + Sized
41 + From<u8>
42 + Eq
43 + Debug
44 + Display
45 + Clone
46 + Copy
47{
48}
49
50impl<
51 U: Add<Output = Self>
52 + Sub<Output = Self>
53 + BitAnd<Output = Self>
54 + Not<Output = Self>
55 + Sized
56 + From<u8>
57 + Eq
58 + Debug
59 + Display
60 + Clone
61 + Copy,
62 > Unsigned for U
63{
64}
65
66/// Check if the given value is a power of 2.
67#[inline(always)]
68pub fn is_pow2<U: Unsigned>(v: U) -> bool {
69 v & (v - U::from(1)) == U::from(0)
70}
71
72/// Assert that the given value is a power of 2.
73#[inline(always)]
74pub fn assert_pow2<U: Unsigned>(v: U) {
75 assert_eq!(v & (v - U::from(1)), U::from(0), "v: {v}");
76}
77
78/// Debug assert that the given value is a power of 2.
79#[inline(always)]
80pub fn debug_assert_pow2<U: Unsigned>(v: U) {
81 debug_assert_eq!(v & (v - U::from(1)), U::from(0), "v: {v}");
82}
83
84/// Check if the given value is aligned with the given align.
85///
86/// Note: The given align must be a power of 2.
87#[inline(always)]
88pub fn is_aligned<U: Unsigned>(align: U, v: U) -> bool {
89 debug_assert_pow2(align);
90 v & (align - U::from(1)) == U::from(0)
91}
92
93/// Assert that the given value is aligned with the given align.
94///
95/// Note: The given align must be a power of 2.
96#[inline(always)]
97pub fn assert_aligned<U: Unsigned>(align: U, v: U) {
98 debug_assert_pow2(align);
99 assert!(is_aligned(align, v), "align: {align}, v: {v}");
100}
101
102/// Debug assert that the given value is aligned with the given align.
103///
104/// Note: The given align must be a power of 2.
105#[inline(always)]
106pub fn debug_assert_aligned<U: Unsigned>(align: U, v: U) {
107 debug_assert_pow2(align);
108 debug_assert!(is_aligned(align, v), "align: {align}, v: {v}");
109}
110
111/// Align up the given value with the given align.
112///
113/// Note: The given align must be a power of 2.
114#[inline(always)]
115pub fn align_up<U: Unsigned>(align: U, v: U) -> U {
116 debug_assert_pow2(align);
117 (v + align - U::from(1)) & !(align - U::from(1))
118}
119
120/// Align down the given value with the given align.
121///
122/// Note: The given align must be a power of 2.
123#[inline(always)]
124pub fn align_down<U: Unsigned>(align: U, v: U) -> U {
125 debug_assert_pow2(align);
126 v & !(align - U::from(1))
127}