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}