|
| 1 | +// Part of the Crubit project, under the Apache License v2.0 with LLVM |
| 2 | +// Exceptions. See /LICENSE for license information. |
| 3 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 4 | + |
| 5 | +// IWYU pragma: private, include "support/rs_std/int.h" |
| 6 | + |
| 7 | +#ifndef CRUBIT_SUPPORT_RS_STD_INT_H_ |
| 8 | +#define CRUBIT_SUPPORT_RS_STD_INT_H_ |
| 9 | + |
| 10 | +#include <compare> |
| 11 | +#include <cstdint> |
| 12 | +#include <type_traits> |
| 13 | + |
| 14 | +#include "support/annotations.h" |
| 15 | + |
| 16 | +namespace rs_std { |
| 17 | + |
| 18 | +// `rs_std::usize` is a C++ representation of the `usize` type from Rust when |
| 19 | +// used as a template argument inside template specializations (such as |
| 20 | +// `rs_std::Option<T>`). This prevents C++ explicit template specialization |
| 21 | +// redefinition errors or overload collisions between `usize`, `u64`, and `u32`. |
| 22 | +class CRUBIT_INTERNAL_RUST_TYPE("usize") CRUBIT_INTERNAL_SAME_ABI usize final { |
| 23 | + public: |
| 24 | + constexpr usize() noexcept = default; |
| 25 | + |
| 26 | + // Implicit constructing conversion from standard integer types. |
| 27 | + // NOLINTNEXTLINE(google-explicit-constructor) |
| 28 | + constexpr usize(::std::uintptr_t value) noexcept : value_(value) {} |
| 29 | + |
| 30 | + constexpr usize(const usize&) noexcept = default; |
| 31 | + constexpr usize& operator=(const usize&) noexcept = default; |
| 32 | + |
| 33 | + // Implicit conversion back to `::std::uintptr_t` for seamless indexing and |
| 34 | + // arithmetic in C++. |
| 35 | + // NOLINTNEXTLINE(google-explicit-constructor) |
| 36 | + constexpr operator ::std::uintptr_t() const noexcept { return value_; } |
| 37 | + |
| 38 | + friend constexpr bool operator==(usize lhs, usize rhs) noexcept = default; |
| 39 | + friend constexpr std::strong_ordering operator<=>( |
| 40 | + usize lhs, usize rhs) noexcept = default; |
| 41 | + |
| 42 | + friend constexpr usize operator+(usize lhs, usize rhs) noexcept { |
| 43 | + return usize(lhs.value_ + rhs.value_); |
| 44 | + } |
| 45 | + friend constexpr usize operator-(usize lhs, usize rhs) noexcept { |
| 46 | + return usize(lhs.value_ - rhs.value_); |
| 47 | + } |
| 48 | + constexpr usize& operator+=(usize rhs) noexcept { |
| 49 | + value_ += rhs.value_; |
| 50 | + return *this; |
| 51 | + } |
| 52 | + constexpr usize& operator-=(usize rhs) noexcept { |
| 53 | + value_ -= rhs.value_; |
| 54 | + return *this; |
| 55 | + } |
| 56 | + |
| 57 | + private: |
| 58 | + ::std::uintptr_t value_ = 0; |
| 59 | +}; |
| 60 | + |
| 61 | +static_assert(sizeof(usize) == sizeof(::std::uintptr_t)); |
| 62 | +static_assert(alignof(usize) == alignof(::std::uintptr_t)); |
| 63 | +static_assert(::std::is_trivially_copyable_v<usize>); |
| 64 | +static_assert(::std::is_trivially_destructible_v<usize>); |
| 65 | + |
| 66 | +// `rs_std::isize` is a C++ representation of the `isize` type from Rust when |
| 67 | +// used as a template argument inside template specializations (such as |
| 68 | +// `rs_std::Option<T>`). This prevents C++ explicit template specialization |
| 69 | +// redefinition errors or overload collisions between `isize`, `i64`, and `i32`. |
| 70 | +class CRUBIT_INTERNAL_RUST_TYPE("isize") CRUBIT_INTERNAL_SAME_ABI isize final { |
| 71 | + public: |
| 72 | + constexpr isize() noexcept = default; |
| 73 | + |
| 74 | + // Implicit constructing conversion from standard integer types. |
| 75 | + // NOLINTNEXTLINE(google-explicit-constructor) |
| 76 | + constexpr isize(::std::intptr_t value) noexcept : value_(value) {} |
| 77 | + |
| 78 | + constexpr isize(const isize&) noexcept = default; |
| 79 | + constexpr isize& operator=(const isize&) noexcept = default; |
| 80 | + |
| 81 | + // Implicit conversion back to `::std::intptr_t` for seamless arithmetic and |
| 82 | + // conversion in C++. |
| 83 | + // NOLINTNEXTLINE(google-explicit-constructor) |
| 84 | + constexpr operator ::std::intptr_t() const noexcept { return value_; } |
| 85 | + |
| 86 | + friend constexpr bool operator==(isize lhs, isize rhs) noexcept = default; |
| 87 | + friend constexpr auto operator<=>(isize lhs, isize rhs) noexcept = default; |
| 88 | + |
| 89 | + friend constexpr isize operator+(isize lhs, isize rhs) noexcept { |
| 90 | + return isize(lhs.value_ + rhs.value_); |
| 91 | + } |
| 92 | + friend constexpr isize operator-(isize lhs, isize rhs) noexcept { |
| 93 | + return isize(lhs.value_ - rhs.value_); |
| 94 | + } |
| 95 | + constexpr isize& operator+=(isize rhs) noexcept { |
| 96 | + value_ += rhs.value_; |
| 97 | + return *this; |
| 98 | + } |
| 99 | + constexpr isize& operator-=(isize rhs) noexcept { |
| 100 | + value_ -= rhs.value_; |
| 101 | + return *this; |
| 102 | + } |
| 103 | + |
| 104 | + private: |
| 105 | + ::std::intptr_t value_ = 0; |
| 106 | +}; |
| 107 | + |
| 108 | +static_assert(sizeof(isize) == sizeof(::std::intptr_t)); |
| 109 | +static_assert(alignof(isize) == alignof(::std::intptr_t)); |
| 110 | +static_assert(::std::is_trivially_copyable_v<isize>); |
| 111 | +static_assert(::std::is_trivially_destructible_v<isize>); |
| 112 | + |
| 113 | +} // namespace rs_std |
| 114 | + |
| 115 | +#endif // CRUBIT_SUPPORT_RS_STD_INT_H_ |
0 commit comments