Skip to main content

alioth/utils/
utils.rs

1// Copyright 2024 Google LLC
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//     https://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
15pub mod endian;
16#[cfg(target_os = "linux")]
17pub mod uds;
18
19use std::sync::atomic::{AtomicU64, Ordering};
20
21pub fn truncate_u64(val: u64, size: u64) -> u64 {
22    val & (u64::MAX >> (64 - (size << 3)))
23}
24
25#[macro_export]
26macro_rules! align_up {
27    ($num:expr, $bits:expr) => {{
28        let mask = (1 << $bits) - 1;
29        ($num.wrapping_add(mask)) & !mask
30    }};
31}
32
33#[macro_export]
34macro_rules! align_up_ty {
35    ($num:expr, $ty:ty) => {{
36        let mask = ::core::mem::align_of::<$ty>() - 1;
37        ($num.wrapping_add(mask)) & !mask
38    }};
39}
40
41#[macro_export]
42macro_rules! align_down {
43    ($num:expr, $bits:expr) => {{
44        let mask = (1 << $bits) - 1;
45        $num & !mask
46    }};
47}
48
49#[macro_export]
50macro_rules! assign_bits {
51    ($dst:expr, $src:expr, $mask:expr) => {
52        $dst = ($dst & !$mask) | ($src & $mask)
53    };
54}
55
56#[macro_export]
57macro_rules! mask_bits {
58    ($dst:expr, $src:expr, $mask:expr) => {
59        ($dst & !$mask) | ($src & $mask)
60    };
61}
62
63#[cfg(target_arch = "x86_64")]
64#[inline]
65pub fn wrapping_sum<'a, T>(data: T) -> u8
66where
67    T: IntoIterator<Item = &'a u8>,
68{
69    data.into_iter().fold(0u8, |accu, e| accu.wrapping_add(*e))
70}
71
72pub fn get_atomic_low32(num: &AtomicU64) -> u32 {
73    num.load(Ordering::Acquire) as u32
74}
75
76pub fn get_atomic_high32(num: &AtomicU64) -> u32 {
77    (num.load(Ordering::Acquire) >> 32) as u32
78}
79
80pub fn set_low32(num: &mut u64, val: u32) {
81    *num &= !0xffff_ffff;
82    *num |= val as u64;
83}
84
85pub fn set_high32(num: &mut u64, val: u32) {
86    *num &= 0xffff_ffff;
87    *num |= (val as u64) << 32;
88}
89
90pub fn set_atomic_low32(num: &AtomicU64, val: u32) {
91    let mut cur = num.load(Ordering::Acquire);
92    set_low32(&mut cur, val);
93    num.store(cur, Ordering::Release)
94}
95
96pub fn set_atomic_high32(num: &AtomicU64, val: u32) {
97    let mut cur = num.load(Ordering::Acquire);
98    set_high32(&mut cur, val);
99    num.store(cur, Ordering::Release)
100}
101
102#[macro_export]
103macro_rules! ffi {
104    ($f:expr) => {{
105        let ret = $f;
106        if ret <= -1 {
107            Err(::std::io::Error::last_os_error())
108        } else {
109            Ok(ret)
110        }
111    }};
112    ($f:expr, $failure:expr) => {{
113        let ret = $f;
114        if ret == $failure {
115            Err(::std::io::Error::last_os_error())
116        } else {
117            Ok(ret)
118        }
119    }};
120}
121
122#[macro_export]
123macro_rules! c_enum {
124    (
125        $(#[$attr:meta])*
126        $vs:vis struct $EnumName:ident($TyName:ty);
127        {
128            $( $(#[$vattr:meta])* $VARIANT:ident = $value:expr;)*
129        }
130    ) => {
131        #[repr(transparent)]
132        #[derive(PartialEq, Eq, Copy, Clone)]
133        $(#[$attr])*
134        $vs struct $EnumName($TyName);
135
136        impl $EnumName {
137            $($(#[$vattr])* pub const $VARIANT: $EnumName = $EnumName($value);)*
138
139            #[allow(dead_code)]
140            pub const fn raw(self) -> $TyName {
141                self.0
142            }
143        }
144
145        impl ::core::fmt::Debug for $EnumName {
146            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
147                f.write_str(stringify!($EnumName))?;
148                match *self {
149                    $($EnumName::$VARIANT => {
150                        f.write_str("::")?;
151                        f.write_str(stringify!($VARIANT))
152                    })*
153                    _ => {
154                        ::core::fmt::Write::write_char(f, '(')?;
155                        ::core::fmt::Debug::fmt(&self.0, f)?;
156                        ::core::fmt::Write::write_char(f, ')')
157                    }
158                }
159            }
160        }
161
162
163        impl From<$EnumName> for $TyName {
164            fn from(value: $EnumName) -> Self {
165                value.0
166            }
167        }
168
169        impl From<$TyName> for $EnumName {
170            fn from(value: $TyName) -> Self {
171                $EnumName(value)
172            }
173        }
174    }
175}
176
177#[cfg(test)]
178#[path = "utils_test.rs"]
179mod tests;