Fork/duplicate a local DEFINE_STRONG_INT_TYPE and DEFINE_STRING_TYPE.

PiperOrigin-RevId: 435355118
diff --git a/rs_bindings_from_cc/blaze_types.h b/rs_bindings_from_cc/blaze_types.h
index af1f34d..10863ff 100644
--- a/rs_bindings_from_cc/blaze_types.h
+++ b/rs_bindings_from_cc/blaze_types.h
@@ -5,13 +5,14 @@
 #ifndef CRUBIT_RS_BINDINGS_FROM_CC_BLAZE_TYPES_H_
 #define CRUBIT_RS_BINDINGS_FROM_CC_BLAZE_TYPES_H_
 
-#include "third_party/absl/strings/string_view.h"
-#include "util/gtl/labs/string_type.h"
+#include <string>
+
+#include "rs_bindings_from_cc/util/string_type.h"
 
 namespace rs_bindings_from_cc {
 
 // Representation of a Blaze label (for example //foo/bar:baz).
-DEFINE_STRING_TYPE(BlazeLabel);
+CRUBIT_DEFINE_STRING_TYPE(BlazeLabel);
 
 }  // namespace rs_bindings_from_cc
 
diff --git a/rs_bindings_from_cc/cmdline.h b/rs_bindings_from_cc/cmdline.h
index bfe701e..6fe85e2 100644
--- a/rs_bindings_from_cc/cmdline.h
+++ b/rs_bindings_from_cc/cmdline.h
@@ -42,7 +42,7 @@
   absl::string_view ir_out() const { return ir_out_; }
   bool do_nothing() const { return do_nothing_; }
 
-  const std::vector<rs_bindings_from_cc::HeaderName>& public_headers() const {
+  const std::vector<HeaderName>& public_headers() const {
     return public_headers_;
   }
 
diff --git a/rs_bindings_from_cc/ir.cc b/rs_bindings_from_cc/ir.cc
index a949ad5..10099d4 100644
--- a/rs_bindings_from_cc/ir.cc
+++ b/rs_bindings_from_cc/ir.cc
@@ -16,8 +16,8 @@
 #include "base/integral_types.h"
 #include "third_party/absl/strings/string_view.h"
 #include "rs_bindings_from_cc/bazel_types.h"
+#include "rs_bindings_from_cc/util/strong_int.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/JSON.h"
-#include "util/intops/strong_int.h"
 
 namespace rs_bindings_from_cc {
 
@@ -27,12 +27,12 @@
 }
 
 template <typename TTag, typename TInt>
-llvm::json::Value toJSON(const util_intops::StrongInt<TTag, TInt> strong_int) {
+llvm::json::Value toJSON(const StrongInt<TTag, TInt> strong_int) {
   return llvm::json::Value(strong_int.value());
 }
 
 template <typename TTag>
-llvm::json::Value toJSON(const gtl::labs::StringType<TTag> string_type) {
+llvm::json::Value toJSON(const StringType<TTag> string_type) {
   return llvm::json::Value(string_type.value());
 }
 
diff --git a/rs_bindings_from_cc/ir.h b/rs_bindings_from_cc/ir.h
index 2411f34..1dadd71 100644
--- a/rs_bindings_from_cc/ir.h
+++ b/rs_bindings_from_cc/ir.h
@@ -25,11 +25,11 @@
 #include "base/logging.h"
 #include "third_party/absl/strings/string_view.h"
 #include "rs_bindings_from_cc/bazel_types.h"
+#include "rs_bindings_from_cc/util/strong_int.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/APSInt.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/ADT/Optional.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/FormatVariadic.h"
 #include "third_party/llvm/llvm-project/llvm/include/llvm/Support/JSON.h"
-#include "util/intops/strong_int.h"
 
 namespace rs_bindings_from_cc {
 
@@ -77,10 +77,10 @@
 // serialization/deserialization at the moment, we need a way to restore graph
 // edges that don't follow the JSON tree structure (for example between types
 // and records). We use DeclIds for this.
-DEFINE_STRONG_INT_TYPE(DeclId, uintptr_t);
+CRUBIT_DEFINE_STRONG_INT_TYPE(DeclId, uintptr_t);
 
 // A numerical ID that uniquely identifies a lifetime.
-DEFINE_STRONG_INT_TYPE(LifetimeId, int);
+CRUBIT_DEFINE_STRONG_INT_TYPE(LifetimeId, int);
 
 // A lifetime.
 struct Lifetime {
diff --git a/rs_bindings_from_cc/util/README b/rs_bindings_from_cc/util/README
new file mode 100644
index 0000000..1244391
--- /dev/null
+++ b/rs_bindings_from_cc/util/README
@@ -0,0 +1,2 @@
+`util` subdirectory contains various utilities. Some of them are
+forked copies of internal Google libraries that are not included in Abseil.
diff --git a/rs_bindings_from_cc/util/string_type.h b/rs_bindings_from_cc/util/string_type.h
new file mode 100644
index 0000000..81717f8
--- /dev/null
+++ b/rs_bindings_from_cc/util/string_type.h
@@ -0,0 +1,261 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Typed strings.
+
+// Example usage:
+//
+//  CRUBIT_DEFINE_STRING_TYPE(Foo);
+//  CRUBIT_DEFINE_STRING_TYPE(Bar);
+//  Foo foo("foo_value");
+//  Bar bar("bar_value");
+//
+// The following two statements will not compile.
+//
+//  foo = bar;
+//
+//  if (foo == bar) { } else { }; ...
+//
+// The strongly-typed types are hashable with the Abseil hashing framework,
+// so they work out of the box with any modern hashing system. For non-Abseil
+// uses, the explicit functors absl::Hash<Foo>, absl::Hash<Bar> may be used:
+//
+//  std::unordered_set<Foo, absl::Hash<Foo>>
+//  __gnu_cxx::hash_map<Bar, int, absl::Hash<Bar>>
+//
+// (But absl::flat_hash_set<Foo> is much better!)
+
+#ifndef CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRING_TYPE_H_
+#define CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRING_TYPE_H_
+
+#include <memory>
+#include <ostream>  // NOLINT
+#include <string>
+
+#include "third_party/absl/container/flat_hash_set.h"
+#include "third_party/absl/flags/marshalling.h"
+#include "third_party/absl/meta/type_traits.h"
+#include "third_party/absl/strings/string_view.h"
+
+// Defines the StringType using StringTypeRepresentation and provides a type
+// alias to string_type_name.  The struct string_type_name ## _tag_ trickery is
+// needed to ensure that a new type is created per string_type_name.
+//
+// StringTypeRepresentation classes, as a rule, should either *be* a string-like
+// object, or should provide a "value()" method that returns a string-like
+// object.  If they can provide more optimal implementations of relational
+// operators, they should define operator== and operator<; all other relational
+// operators are defined in terms of those.  If they can provide more optimal
+// implementations of AbslHashValue or operator<<, they should provide those as
+// well.
+#define CRUBIT_DEFINE_STRING_TYPE_AS(string_type_name,                \
+                                     StringTypeRepresentation)        \
+  struct string_type_name##_tag_ {                                    \
+    static absl::string_view TypeName() { return #string_type_name; } \
+    using Representation = StringTypeRepresentation;                  \
+  };                                                                  \
+  using string_type_name =                                            \
+      ::rs_bindings_from_cc::StringType<string_type_name##_tag_>;
+
+#define CRUBIT_DEFINE_STRING_TYPE(string_type_name) \
+  CRUBIT_DEFINE_STRING_TYPE_AS(string_type_name, std::string);
+
+namespace rs_bindings_from_cc {
+
+// StringType provides these operations:
+//   * relational operators (==, !=, <, <=, >, >=)
+//   * compare (future <=> operator)
+//   * AbslHashValue
+//   * streaming with operator<<
+//   * value(), which should return a string-like object (const string&,
+//     absl::string_view, ShortString<N>, etc.)
+//
+// It is parameterized here by a "TagAndRepresentation" struct.  It's a unique
+// struct defined in each CRUBIT_DEFINE_STRING_TYPE_AS macro invocation, so
+// every StringType is its own unique, strong type.  In addition, it provides a
+// static TypeName() method that returns the name of the type, and it provides a
+// "Representation" type alias which is held as a member by each StringType
+// instance.
+//
+// When a StringType instance method is called, it will first try to dispatch
+// the call directly to the Representation instance.  If the Representation
+// class doesn't have this method, StringType will call value() on its
+// representation instance, and then call the method on the returned value.
+// We do this dispatch at compile-time using <internal link>.
+template <typename TagAndRepresentation>
+class StringType {
+ public:
+  // Shorthand.
+  using Rep = typename TagAndRepresentation::Representation;
+
+ private:
+  // Using SFINAE, you can "rank" implementations using this mechanism.  Given
+  // two acceptable implementations that substitute correctly, the compiler will
+  // choose the one that requires fewer type conversions, so a method given a
+  // Rank0 object will prefer an implementation that accepts a Rank0 type to an
+  // implementation that accepts a Rank1 type, since a Rank1 argument requires a
+  // derived->base conversion.
+  struct Rank1 {};
+  struct Rank0 : Rank1 {};
+
+  // This would normally be declared at the bottom of the class, but we need to
+  // move it up here to satisfy the compiler.
+  //
+  // Since the return type of value(), below, is either the same as the return
+  // type of t_.value(), if such a method exists, or t_ itself, if t_.value()
+  // doesn't exists, we need to declare our t_ up here so the compiler knows
+  // what it is and whether it has a value() method.
+  Rep t_;
+
+  // These must be defined before value() is defined below, since value()'s
+  // return type is determined by what these methods return.
+  template <typename T>
+  static auto DispatchValue(const T& t, Rank0) -> decltype(t.value()) {
+    return t.value();
+  }
+  static const Rep& DispatchValue(const Rep& t, Rank1) { return t; }
+
+ public:
+  StringType() = default;
+  template <typename T, typename = absl::enable_if_t<
+                            std::is_constructible<Rep, T&&>::value>>
+  explicit StringType(T&& value) : t_(std::forward<T>(value)) {}
+
+  // Returns the name of this StringType, as used in code.
+  static absl::string_view TypeName() {
+    return TagAndRepresentation::TypeName();
+  }
+
+  ABSL_DEPRECATED("Use TypeName()")
+  static absl::string_view TypeId() { return TypeName(); }
+
+  // Returns the result of the representation's value() method, or the
+  // representation itself if the representation has no value() method.
+  auto value() const -> decltype(DispatchValue(t_, Rank0{})) {
+    return DispatchValue(t_, Rank0{});
+  }
+
+  bool empty() const { return DispatchEmpty(t_, Rank0{}); }
+
+  // If you want to optimize your relational methods, you need only implement
+  // these three: compare, operator==, and operator<.
+  int compare(const StringType& other) const {
+    return DispatchCompare(*this, other, Rank0{});
+  }
+  friend bool operator==(const StringType& left, const StringType& right) {
+    return DispatchEquals(left, right, Rank0{});
+  }
+  friend bool operator<(const StringType& left, const StringType& right) {
+    return DispatchLessThan(left, right, Rank0{});
+  }
+
+  // These methods are defined in terms of the above.
+  friend bool operator!=(const StringType& left, const StringType& right) {
+    return !(left == right);
+  }
+  friend bool operator>(const StringType& left, const StringType& right) {
+    return right < left;
+  }
+  friend bool operator<=(const StringType& left, const StringType& right) {
+    return !(left > right);
+  }
+  friend bool operator>=(const StringType& left, const StringType& right) {
+    return !(left < right);
+  }
+
+  template <typename H>
+  friend H AbslHashValue(H h, const StringType& s) {
+    return s.DispatchHash(std::move(h), Rank0{});
+  }
+
+  friend std::ostream& operator<<(std::ostream& os, const StringType& s) {
+    return DispatchOstream(os, s.t_, Rank0{});
+  }
+
+ private:
+  template <typename T>
+  static auto DispatchEmpty(const T& t, Rank0) -> decltype(t.empty()) {
+    return t.empty();
+  }
+  static bool DispatchEmpty(const Rep& t, Rank1) {
+    return DispatchValue(t, Rank0{}).empty();
+  }
+
+  // This overload exists specifically for absl::Cord, which spells 'compare' as
+  // 'Compare'.
+  template <typename T>
+  static auto DispatchCompare(const T& left, const T& right, Rank0)
+      -> decltype(left.value().Compare(right.value())) {
+    return left.value().Compare(right.value());
+  }
+  template <typename T>
+  static auto DispatchCompare(const T& left, const T& right, Rank0)
+      -> decltype(left.t_.compare(right.t_)) {
+    return left.t_.compare(right.t_);
+  }
+  template <typename T>
+  static auto DispatchCompare(const T& left, const T& right, Rank1)
+      -> decltype(left.value().compare(right.value())) {
+    return left.value().compare(right.value());
+  }
+
+  template <typename T>
+  static auto DispatchEquals(const T& left, const T& right, Rank0)
+      -> decltype(left.t_ == right.t_) {
+    return left.t_ == right.t_;
+  }
+  static bool DispatchEquals(const StringType& left, const StringType& right,
+                             Rank1) {
+    return left.value() == right.value();
+  }
+
+  template <typename T>
+  static auto DispatchLessThan(const T& left, const T& right, Rank0)
+      -> decltype(left.t_ < right.t_) {
+    return left.t_ < right.t_;
+  }
+  static bool DispatchLessThan(const StringType& left, const StringType& right,
+                               Rank1) {
+    return left.value() < right.value();
+  }
+
+  template <
+      typename H, typename T = Rep,
+      typename Hashable = decltype(absl::Hash<T>()(std::declval<const T&>()))>
+  H DispatchHash(H h, Rank0) const {
+    return H::combine(std::move(h), t_);
+  }
+  template <typename H>
+  H DispatchHash(H h, Rank1) const {
+    return H::combine(std::move(h), value());
+  }
+
+  template <typename T>
+  static auto DispatchOstream(std::ostream& os, const T& t, Rank0)
+      -> decltype(os << t) {
+    return os << t;
+  }
+  static std::ostream& DispatchOstream(std::ostream& os, const Rep& t, Rank1) {
+    return os << DispatchValue(t, Rank0{});
+  }
+};
+
+// Allows typed strings to be used as ABSL_FLAG values.
+//
+// This is equivalent in behavior to just using a raw std::string.
+template <typename TagAndRepresentation>
+bool AbslParseFlag(absl::string_view text,
+                   StringType<TagAndRepresentation>* out, std::string* error) {
+  *out = StringType<TagAndRepresentation>(text);
+  return true;
+}
+
+template <typename TagAndRepresentation>
+std::string AbslUnparseFlag(const StringType<TagAndRepresentation>& val) {
+  return absl::UnparseFlag(std::string(val.value()));
+}
+
+}  // namespace rs_bindings_from_cc
+
+#endif  // CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRING_TYPE_H_
diff --git a/rs_bindings_from_cc/util/strong_int.h b/rs_bindings_from_cc/util/strong_int.h
new file mode 100644
index 0000000..1e11223
--- /dev/null
+++ b/rs_bindings_from_cc/util/strong_int.h
@@ -0,0 +1,658 @@
+// Part of the Crubit project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// StrongInt<T> is a simple template class mechanism for defining "logical"
+// integer-like class types that support almost all of the same functionality
+// as native integer types, but which prevents assignment, construction, and
+// other operations from other integer-like types.  In other words, you cannot
+// assign from raw integer types or other StrongInt<> types, nor can you do
+// most arithmetic or logical operations.  This provides a simple form of
+// dimensionality in that you can add two instances of StrongInt<T>, producing
+// a StrongInt<T>, but you can not add a StrongInt<T> and a raw T nor can you
+// add a StrongInt<T> and a StrongInt<U>.  Details on supported operations are
+// below.
+//
+// In addition to type strength, StrongInt provides a way to inject (optional)
+// validation of the various operations.  This allows you to define StrongInt
+// types that check for overflow conditions and react in standard or custom
+// ways.
+//
+// A StrongInt<T> with a NullStrongIntValidator should compile away to a raw T
+// in optimized mode.  What this means is that the generated assembly for:
+//
+//   int64 foo = 123;
+//   int64 bar = 456;
+//   int64 baz = foo + bar;
+//   constexpr int64 fubar = 789;
+//
+// ...should be identical to the generated assembly for:
+//
+//    CRUBIT_DEFINE_STRONG_INT_TYPE(MyStrongInt, int64);
+//    MyStrongInt foo(123);
+//    MyStrongInt bar(456);
+//    MyStrongInt baz = foo + bar;
+//    constexpr MyStrongInt fubar(789);
+//
+// Since the methods are all inline and non-virtual and the class has just
+// one data member, the compiler can erase the StrongInt class entirely in its
+// code-generation phase.  This also means that you can pass StrongInt<T>
+// around by value just as you would a raw T.
+//
+// It is important to note that StrongInt does NOT generate compile time
+// warnings or errors for overflows on implicit constant conversions.
+// For example, the below demonstrates a case where the 2 are not equivalent
+// at compile time and can lead to subtle initialization bugs:
+//
+//    CRUBIT_DEFINE_STRONG_INT_TYPE(MyStrongInt8, int8);
+//    int8 foo = 1024;        // Compile error: const conversion to ...
+//    MyStrongInt8 foo(1024); // Compiles ok: foo has undefined / 0 value.
+//
+// Usage:
+//   CRUBIT_DEFINE_STRONG_INT_TYPE(Name, NativeType);
+//
+//     Defines a new StrongInt type named 'Name' in the current namespace with
+//     no validation of operations.
+//
+//     Name: The desired name for the new StrongInt typedef.  Must be unique
+//         within the current namespace.
+//     NativeType: The primitive integral type this StrongInt will hold, as
+//         defined by std::numeric_limits::is_integer (see <type_traits>).
+//
+//  StrongInt<TagType, NativeType, ValidatorType = NullStrongIntValidator>
+//
+//    Creates a new StrongInt instance directly.
+//
+//     TagType: The unique type which discriminates this StrongInt<T> from
+//         other StrongInt<U> types.
+//     NativeType: The primitive integral type this StrongInt will hold, as
+//         defined by std::numeric_limits::is_integer (see <type_traits>).
+//     ValidatorType: The type of validation used by this StrongInt type.  A
+//         few pre-built validator types are provided here, but the caller can
+//         define any custom validator they desire.
+//
+// Supported operations:
+//     StrongInt<T> = StrongInt<T>
+//     !StrongInt<T> => bool
+//     ~StrongInt<T> => StrongInt<T>
+//     -StrongInt<T> => StrongInt<T>
+//     +StrongInt<T> => StrongInt<T>
+//     ++StrongInt<T> => StrongInt<T>
+//     StrongInt<T>++ => StrongInt<T>
+//     --StrongInt<T> => StrongInt<T>
+//     StrongInt<T>-- => StrongInt<T>
+//     StrongInt<T> + StrongInt<T> => StrongInt<T>
+//     StrongInt<T> - StrongInt<T> => StrongInt<T>
+//     StrongInt<T> * (numeric type) => StrongInt<T>
+//     StrongInt<T> / (numeric type) => StrongInt<T>
+//     StrongInt<T> % (numeric type) => StrongInt<T>
+//     StrongInt<T> << (numeric type) => StrongInt<T>
+//     StrongInt<T> >> (numeric type) => StrongInt<T>
+//     StrongInt<T> & StrongInt<T> => StrongInt<T>
+//     StrongInt<T> | StrongInt<T> => StrongInt<T>
+//     StrongInt<T> ^ StrongInt<T> => StrongInt<T>
+//
+//   For binary operations, the equivalent op-equal (eg += vs. +) operations are
+//   also supported.  Other operator combinations should cause compile-time
+//   errors.
+//
+//   This class also provides a .value() accessor method and defines a hash
+//   functor that allows the IntType to be used as key to hashable containers.
+//
+// Validators:
+//   NullStrongIntValidator: Do no validation.  This should be entirely
+//       optimized away by the compiler.
+
+#ifndef CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRONG_INT_H_
+#define CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRONG_INT_H_
+
+#include <cstdint>
+#include <hash_map>
+#include <iosfwd>
+#include <iterator>
+#include <limits>
+#include <ostream>
+#include <type_traits>
+#include <utility>
+
+#include "third_party/absl/base/macros.h"
+#include "third_party/absl/meta/type_traits.h"
+#include "third_party/absl/strings/string_view.h"
+
+namespace rs_bindings_from_cc {
+
+// Define the validators which can be plugged-in to make StrongInt resilient to
+// things like overflows. This is a do-nothing implementation of the
+// compile-time interface.
+//
+// NOTE: For all validation functions that operate on an existing StrongInt<T>,
+// the type argument 'T' *must* be StrongInt<T>::ValueType (the int type being
+// strengthened).
+//
+struct NullStrongIntValidator {
+  // Note that this templated default implementation has an arbitrary bool
+  // return value for the sole purpose of conforming to c++11 constexpr.
+  //
+  // Custom validator implementations can choose to return void or use a similar
+  // return value constexpr construct if constexpr initialization is desirable.
+  //
+  // The StrongInt class does not care about or use the returned value. Any
+  // returned value is solely there to allow the constexpr declaration; custom
+  // validators can only fail / abort when detecting an invalid value.
+  //
+  // For example, other than the constexpr behavior, the below 2 custom
+  // validator implementations are logically equivalent:
+  //
+  //   template<typename T, typename U>
+  //   static void ValidateInit(U arg) {
+  //     if (arg < 0) LOG(FATAL) << "arg < 0";
+  //   }
+  //
+  //   template<typename T, typename U>
+  //   static constexpr bool ValidateInit(U arg) {
+  //     return (arg < 0) ? (LOG(FATAL) << "arg < 0", false) : false;
+  //   }
+  //
+  // A constexpr implementation has the added advantage that the validation can
+  // take place (fail) at compile time.
+
+  // Verify initialization of StrongInt<T> from arg, type U.
+  template<typename T, typename U>
+  static constexpr bool ValidateInit(U arg) { return true; }
+  // Verify -value.
+  template <typename T>
+  static constexpr bool ValidateNegate(T /*value*/) {
+    return true;
+  }
+  // Verify ~value;
+  template <typename T>
+  static constexpr bool ValidateBitNot(T /*value*/) {
+    return true;
+  }
+  // Verify lhs + rhs.
+  template <typename T>
+  static constexpr bool ValidateAdd(T /*lhs*/, T /*rhs*/) {
+    return true;
+  }
+  // Verify lhs - rhs.
+  template <typename T>
+  static constexpr bool ValidateSubtract(T /*lhs*/, T /*rhs*/) {
+    return true;
+  }
+  // Verify lhs * rhs.
+  template <typename T, typename U>
+  static constexpr bool ValidateMultiply(T /*lhs*/, U /*rhs*/) {
+    return true;
+  }
+  // Verify lhs / rhs.
+  template <typename T, typename U>
+  static constexpr bool ValidateDivide(T /*lhs*/, U /*rhs*/) {
+    return true;
+  }
+  // Verify lhs % rhs.
+  template <typename T, typename U>
+  static constexpr bool ValidateModulo(T /*lhs*/, U /*rhs*/) {
+    return true;
+  }
+  // Verify lhs << rhs.
+  template <typename T>
+  static constexpr bool ValidateLeftShift(T /*lhs*/, int64_t /*rhs*/) {
+    return true;
+  }
+  // Verify lhs >> rhs.
+  template <typename T>
+  static constexpr bool ValidateRightShift(T /*lhs*/, int64_t /*rhs*/) {
+    return true;
+  }
+  // Verify lhs & rhs.
+  template <typename T>
+  static constexpr bool ValidateBitAnd(T /*lhs*/, T /*rhs*/) {
+    return true;
+  }
+  // Verify lhs | rhs.
+  template <typename T>
+  static constexpr bool ValidateBitOr(T /*lhs*/, T /*rhs*/) {
+    return true;
+  }
+  // Verify lhs ^ rhs.
+  template <typename T>
+  static constexpr bool ValidateBitXor(T /*lhs*/, T /*rhs*/) {
+    return true;
+  }
+};
+
+// Holds an integer value (of type NativeType) and behaves as a NativeType by
+// exposing assignment, unary, comparison, and arithmetic operators.
+//
+// This class is NOT thread-safe.
+template<typename TagType, typename NativeType,
+         typename ValidatorType = NullStrongIntValidator>
+class StrongInt {
+ public:
+  typedef NativeType ValueType;
+
+  struct ABSL_DEPRECATED("Use absl::Hash instead") Hasher {
+    size_t operator()(const StrongInt &x) const {
+      return static_cast<size_t>(x.value());
+    }
+  };
+
+  static constexpr absl::string_view TypeName() { return TagType::TypeName(); }
+
+  // Default value initialization.
+  constexpr StrongInt()
+      : value_((ValidatorType::template ValidateInit<ValueType>(NativeType()),
+                NativeType())) {}
+
+  // Explicit initialization from another StrongInt type that has an
+  // implementation of:
+  //
+  //    ToType StrongIntConvert(FromType source, ToType*);
+  //
+  // This uses Argument Dependent Lookup (ADL) to find which function to
+  // call.
+  //
+  // Example: Assume you have two StrongInt types.
+  //
+  //      CRUBIT_DEFINE_STRONG_INT_TYPE(Bytes, int64);
+  //      CRUBIT_DEFINE_STRONG_INT_TYPE(Megabytes, int64);
+  //
+  //  If you want to be able to (explicitly) construct an instance of Bytes from
+  //  an instance of Megabytes, simply define a converter function in the same
+  //  namespace as either Bytes or Megabytes (or both):
+  //
+  //      Megabytes StrongIntConvert(Bytes arg, Megabytes* /* unused */) {
+  //        return Megabytes((arg >> 20).value());
+  //      };
+  //
+  //  The second argument is needed to differentiate conversions, and it always
+  //  passed as NULL.
+  template <typename ArgTagType, typename ArgNativeType,
+            typename ArgValidatorType>
+  explicit constexpr StrongInt(
+      StrongInt<ArgTagType, ArgNativeType, ArgValidatorType> arg)
+      // We have to pass both the "from" type and the "to" type as args for the
+      // conversions to be differentiated.  The converter can not be a template
+      // because explicit template call syntax defeats ADL.
+      : value_(
+            StrongIntConvert(arg, static_cast<StrongInt *>(nullptr)).value()) {}
+
+  // Explicit initialization from a numeric primitive.
+  template <
+      class T,
+      class = std::enable_if_t<std::is_same_v<
+          decltype(static_cast<ValueType>(std::declval<T>())), ValueType>>>
+  explicit constexpr StrongInt(T init_value)
+      : value_((ValidatorType::template ValidateInit<ValueType>(init_value),
+                static_cast<ValueType>(init_value))) {}
+
+  // Use the default copy constructor, assignment, and destructor.
+
+  // Accesses the raw value.
+  constexpr ValueType value() const { return value_; }
+
+  // Accesses the raw value, with cast.
+  // Primarily for compatibility with int-type.h
+  template <typename ValType>
+  constexpr ValType value() const { return static_cast<ValType>(value_); }
+
+  // Explicitly cast the raw value only if the underlying value is convertible
+  // to T.
+  template <typename T,
+            typename = absl::enable_if_t<absl::conjunction<
+                std::bool_constant<std::numeric_limits<T>::is_integer>,
+                std::is_convertible<ValueType, T>>::value>>
+  constexpr explicit operator T() const {
+    return value_;
+  }
+
+  // Metadata functions.
+  static constexpr StrongInt Max() {
+    return StrongInt(std::numeric_limits<ValueType>::max());
+  }
+  static constexpr StrongInt Min() {
+    return StrongInt(std::numeric_limits<ValueType>::min());
+  }
+
+  // Unary operators.
+  bool operator!() const {
+    return value_ == 0;
+  }
+  const StrongInt operator+() const {
+    return StrongInt(value_);
+  }
+  const StrongInt operator-() const {
+    ValidatorType::template ValidateNegate<ValueType>(value_);
+    return StrongInt(-value_);
+  }
+  const StrongInt operator~() const {
+    ValidatorType::template ValidateBitNot<ValueType>(value_);
+    return StrongInt(ValueType(~value_));
+  }
+
+  // Increment and decrement operators.
+  StrongInt &operator++() {  // ++x
+    ValidatorType::template ValidateAdd<ValueType>(value_, ValueType(1));
+    ++value_;
+    return *this;
+  }
+  const StrongInt operator++(int postfix_flag) {  // x++
+    ValidatorType::template ValidateAdd<ValueType>(value_, ValueType(1));
+    StrongInt temp(*this);
+    ++value_;
+    return temp;
+  }
+  StrongInt &operator--() {  // --x
+    ValidatorType::template ValidateSubtract<ValueType>(value_, ValueType(1));
+    --value_;
+    return *this;
+  }
+  const StrongInt operator--(int postfix_flag) {  // x--
+    ValidatorType::template ValidateSubtract<ValueType>(value_, ValueType(1));
+    StrongInt temp(*this);
+    --value_;
+    return temp;
+  }
+
+  // Action-Assignment operators.
+  StrongInt &operator+=(StrongInt arg) {
+    ValidatorType::template ValidateAdd<ValueType>(value_, arg.value());
+    value_ += arg.value();
+    return *this;
+  }
+  StrongInt &operator-=(StrongInt arg) {
+    ValidatorType::template ValidateSubtract<ValueType>(value_, arg.value());
+    value_ -= arg.value();
+    return *this;
+  }
+  template<typename ArgType>
+  StrongInt &operator*=(ArgType arg) {
+    ValidatorType::template ValidateMultiply<ValueType, ArgType>(value_, arg);
+    value_ *= arg;
+    return *this;
+  }
+  template<typename ArgType>
+  StrongInt &operator/=(ArgType arg) {
+    ValidatorType::template ValidateDivide<ValueType, ArgType>(value_, arg);
+    value_ /= arg;
+    return *this;
+  }
+  template<typename ArgType>
+  StrongInt &operator%=(ArgType arg) {
+    ValidatorType::template ValidateModulo<ValueType, ArgType>(value_, arg);
+    value_ %= arg;
+    return *this;
+  }
+  StrongInt &operator<<=(int64_t arg) {  // NOLINT(whitespace/operators)
+    ValidatorType::template ValidateLeftShift<ValueType>(value_, arg);
+    value_ <<= arg;
+    return *this;
+  }
+  StrongInt &operator>>=(int64_t arg) {  // NOLINT(whitespace/operators)
+    ValidatorType::template ValidateRightShift<ValueType>(value_, arg);
+    value_ >>= arg;
+    return *this;
+  }
+  StrongInt &operator&=(StrongInt arg) {
+    ValidatorType::template ValidateBitAnd<ValueType>(value_, arg.value());
+    value_ &= arg.value();
+    return *this;
+  }
+  StrongInt &operator|=(StrongInt arg) {
+    ValidatorType::template ValidateBitOr<ValueType>(value_, arg.value());
+    value_ |= arg.value();
+    return *this;
+  }
+  StrongInt &operator^=(StrongInt arg) {
+    ValidatorType::template ValidateBitXor<ValueType>(value_, arg.value());
+    value_ ^= arg.value();
+    return *this;
+  }
+
+  template <typename H>
+  friend H AbslHashValue(H h, const StrongInt &i) {
+    return H::combine(std::move(h), i.value_);
+  }
+
+ private:
+  // The integer value of type ValueType.
+  ValueType value_;
+
+  static_assert(std::numeric_limits<ValueType>::is_integer,
+                "invalid integer type for strong int");
+};
+
+// Provide the << operator, primarily for logging purposes.
+template<typename TagType, typename ValueType, typename ValidatorType>
+std::ostream &operator<<(std::ostream &os,
+                         StrongInt<TagType, ValueType, ValidatorType> arg) {
+  return os << arg.value();
+}
+
+// Provide the << operator, primarily for logging purposes. Specialized for int8
+// so that an integer and not a character is printed.
+template <typename TagType, typename ValidatorType>
+std::ostream &operator<<(std::ostream &os,
+                         StrongInt<TagType, int8_t, ValidatorType> arg) {
+  return os << static_cast<int>(arg.value());
+}
+
+// Provide the << operator, primarily for logging purposes. Specialized for
+// uint8 so that an integer and not a character is printed.
+template <typename TagType, typename ValidatorType>
+std::ostream &operator<<(std::ostream &os,
+                         StrongInt<TagType, uint8_t, ValidatorType> arg) {
+  return os << static_cast<unsigned int>(arg.value());
+}
+
+// Define operators that take two StrongInt arguments.
+#define CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(op, validator)          \
+  template <typename TagType, typename ValueType, typename ValidatorType> \
+  constexpr StrongInt<TagType, ValueType, ValidatorType> operator op(     \
+      StrongInt<TagType, ValueType, ValidatorType> lhs,                   \
+      StrongInt<TagType, ValueType, ValidatorType> rhs) {                 \
+    return ValidatorType::template validator<ValueType>(lhs.value(),      \
+                                                        rhs.value()),     \
+           StrongInt<TagType, ValueType, ValidatorType>(                  \
+               static_cast<ValueType>(lhs.value() op rhs.value()));       \
+  }
+CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(+, ValidateAdd);
+CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(-, ValidateSubtract);
+CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(&, ValidateBitAnd);
+CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(|, ValidateBitOr);
+CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP(^, ValidateBitXor);
+#undef CRUBIT_STRONG_INT_VS_STRONG_INT_BINARY_OP
+
+// Define operators that take one StrongInt and one native integer argument.
+// These operators are defined in terms of their op-equal member function
+// cousins, mostly.
+#define CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(op, validator)              \
+  template <typename TagType, typename ValueType, typename ValidatorType,  \
+            typename NumType>                                              \
+  constexpr StrongInt<TagType, ValueType, ValidatorType> operator op(      \
+      StrongInt<TagType, ValueType, ValidatorType> lhs, NumType rhs) {     \
+    return ValidatorType::template validator<ValueType>(lhs.value(), rhs), \
+           StrongInt<TagType, ValueType, ValidatorType>(                   \
+               static_cast<ValueType>(lhs.value() op rhs));                \
+  }
+// This is used for commutative operators between one StrongInt and one native
+// integer argument.  That is a long way of saying "multiplication".
+#define CRUBIT_NUMERIC_VS_STRONG_INT_BINARY_OP(op, validator)              \
+  template <typename TagType, typename ValueType, typename ValidatorType,  \
+            typename NumType>                                              \
+  constexpr StrongInt<TagType, ValueType, ValidatorType> operator op(      \
+      NumType lhs, StrongInt<TagType, ValueType, ValidatorType> rhs) {     \
+    return ValidatorType::template validator<ValueType>(rhs.value(), lhs), \
+           StrongInt<TagType, ValueType, ValidatorType>(                   \
+               static_cast<ValueType>(rhs.value() op lhs));                \
+  }
+CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(*, ValidateMultiply);
+CRUBIT_NUMERIC_VS_STRONG_INT_BINARY_OP(*, ValidateMultiply);
+CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(/, ValidateDivide);
+CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(%, ValidateModulo);
+CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(<<, ValidateLeftShift);
+CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP(>>, ValidateRightShift);
+#undef CRUBIT_STRONG_INT_VS_NUMERIC_BINARY_OP
+#undef CRUBIT_NUMERIC_VS_STRONG_INT_BINARY_OP
+
+// Define comparison operators.  We allow all comparison operators.
+#define CRUBIT_STRONG_INT_COMPARISON_OP(op)                               \
+  template <typename TagType, typename ValueType, typename ValidatorType> \
+  constexpr bool operator op(                                             \
+      StrongInt<TagType, ValueType, ValidatorType> lhs,                   \
+      StrongInt<TagType, ValueType, ValidatorType> rhs) {                 \
+    return lhs.value() op rhs.value();                                    \
+  }
+CRUBIT_STRONG_INT_COMPARISON_OP(==);  // NOLINT(whitespace/operators)
+CRUBIT_STRONG_INT_COMPARISON_OP(!=);  // NOLINT(whitespace/operators)
+CRUBIT_STRONG_INT_COMPARISON_OP(<);   // NOLINT(whitespace/operators)
+CRUBIT_STRONG_INT_COMPARISON_OP(<=);  // NOLINT(whitespace/operators)
+CRUBIT_STRONG_INT_COMPARISON_OP(>);   // NOLINT(whitespace/operators)
+CRUBIT_STRONG_INT_COMPARISON_OP(>=);  // NOLINT(whitespace/operators)
+#undef CRUBIT_STRONG_INT_COMPARISON_OP
+
+// Support for-range loops. Enables easier looping over ranges of StrongInts,
+// especially looping over sub-ranges of StrongVectors.
+template <typename IntType>
+class StrongIntRange {
+ public:
+  // Iterator over the indices.
+  class StrongIntRangeIterator {
+   public:
+    using value_type = IntType;
+    using difference_type = IntType;
+    using reference = const IntType &;
+    using pointer = const IntType *;
+    using iterator_category = std::input_iterator_tag;
+
+    explicit StrongIntRangeIterator(IntType initial) : current_(initial) {}
+    bool operator!=(const StrongIntRangeIterator &other) const {
+      return current_ != other.current_;
+    }
+    bool operator==(const StrongIntRangeIterator &other) const {
+      return current_ == other.current_;
+    }
+    value_type operator*() const { return current_; }
+    pointer operator->() const { return &current_; }
+    StrongIntRangeIterator &operator++() {
+      ++current_;
+      return *this;
+    }
+    StrongIntRangeIterator operator++(int) {
+      StrongIntRangeIterator old_iter = *this;
+      ++current_;
+      return old_iter;
+    }
+
+   private:
+    IntType current_;
+  };
+
+  // Loops from IntType(0) up to (but not including) end.
+  explicit StrongIntRange(IntType end) : begin_(IntType(0)), end_(end) {}
+  // Loops from begin up to (but not including) end.
+  StrongIntRange(IntType begin, IntType end) : begin_(begin), end_(end) {}
+  StrongIntRangeIterator begin() const { return begin_; }
+  StrongIntRangeIterator end() const { return end_; }
+
+ private:
+  const StrongIntRangeIterator begin_;
+  const StrongIntRangeIterator end_;
+};
+
+template <typename IntType>
+StrongIntRange<IntType> MakeStrongIntRange(IntType end) {
+  return StrongIntRange<IntType>(end);
+}
+
+template <typename IntType>
+StrongIntRange<IntType> MakeStrongIntRange(IntType begin, IntType end) {
+  return StrongIntRange<IntType>(begin, end);
+}
+
+// Type trait for detecting if a type T is a StrongInt type.
+template <typename T>
+struct IsStrongInt : public std::false_type {};
+
+template <typename... Ts>
+struct IsStrongInt<StrongInt<Ts...>> : public std::true_type {};
+
+}  // namespace rs_bindings_from_cc
+
+// Defines the StrongInt using value_type and typedefs it to type_name, with no
+// validation of under/overflow situations.
+// The struct int_type_name ## _tag_ trickery is needed to ensure that a new
+// type is created per type_name.
+#define CRUBIT_DEFINE_STRONG_INT_TYPE(type_name, value_type)             \
+  struct type_name##_strong_int_tag_ {                                   \
+    static constexpr absl::string_view TypeName() { return #type_name; } \
+  };                                                                     \
+  typedef ::rs_bindings_from_cc::StrongInt<                              \
+      type_name##_strong_int_tag_, value_type,                           \
+      ::rs_bindings_from_cc::NullStrongIntValidator>                     \
+      type_name;
+
+// Allow StrongInt to be used as a key to hashable containers.
+HASH_NAMESPACE_DECLARATION_START
+template <typename Tag, typename Value, typename Validator>
+struct hash<rs_bindings_from_cc::StrongInt<Tag, Value, Validator>>
+    : ::rs_bindings_from_cc::StrongInt<Tag, Value, Validator>::Hasher {};
+HASH_NAMESPACE_DECLARATION_END
+
+// Numeric_limits override for strong int.
+namespace std {
+
+template <typename TagType, typename NativeType, typename ValidatorType>
+struct numeric_limits<
+    rs_bindings_from_cc::StrongInt<TagType, NativeType, ValidatorType>> {
+ private:
+  using StrongIntT =
+      rs_bindings_from_cc::StrongInt<TagType, NativeType, ValidatorType>;
+
+ public:
+  static constexpr bool is_specialized = true;
+  static constexpr bool is_signed = numeric_limits<NativeType>::is_signed;
+  static constexpr bool is_integer = numeric_limits<NativeType>::is_integer;
+  static constexpr bool is_exact = numeric_limits<NativeType>::is_exact;
+  static constexpr bool has_infinity = numeric_limits<NativeType>::has_infinity;
+  static constexpr bool has_quiet_NaN =
+      numeric_limits<NativeType>::has_quiet_NaN;
+  static constexpr bool has_signaling_NaN =
+      numeric_limits<NativeType>::has_signaling_NaN;
+  static constexpr float_denorm_style has_denorm =
+      numeric_limits<NativeType>::has_denorm;
+  static constexpr bool has_denorm_loss =
+      numeric_limits<NativeType>::has_denorm_loss;
+  static constexpr float_round_style round_style =
+      numeric_limits<NativeType>::round_style;
+  static constexpr bool is_iec559 = numeric_limits<NativeType>::is_iec559;
+  static constexpr bool is_bounded = numeric_limits<NativeType>::is_bounded;
+  static constexpr bool is_modulo = numeric_limits<NativeType>::is_modulo;
+  static constexpr int digits = numeric_limits<NativeType>::digits;
+  static constexpr int digits10 = numeric_limits<NativeType>::digits10;
+  static constexpr int max_digits10 = numeric_limits<NativeType>::max_digits10;
+  static constexpr int radix = numeric_limits<NativeType>::radix;
+  static constexpr int min_exponent = numeric_limits<NativeType>::min_exponent;
+  static constexpr int min_exponent10 =
+      numeric_limits<NativeType>::min_exponent10;
+  static constexpr int max_exponent = numeric_limits<NativeType>::max_exponent;
+  static constexpr int max_exponent10 =
+      numeric_limits<NativeType>::max_exponent10;
+  static constexpr bool traps = numeric_limits<NativeType>::traps;
+  static constexpr bool tinyness_before =
+      numeric_limits<NativeType>::tinyness_before;
+
+  static constexpr StrongIntT(min)() { return StrongIntT(StrongIntT::Min()); }
+  static constexpr StrongIntT lowest() { return StrongIntT(StrongIntT::Min()); }
+  static constexpr StrongIntT(max)() { return StrongIntT(StrongIntT::Max()); }
+  static constexpr StrongIntT epsilon() { return StrongIntT(); }
+  static constexpr StrongIntT round_error() { return StrongIntT(); }
+  static constexpr StrongIntT infinity() { return StrongIntT(); }
+  static constexpr StrongIntT quiet_NaN() { return StrongIntT(); }
+  static constexpr StrongIntT signaling_NaN() { return StrongIntT(); }
+  static constexpr StrongIntT denorm_min() { return StrongIntT(); }
+};
+
+}  // namespace std
+
+#endif  // CRUBIT_RS_BINDINGS_FROM_CC_UTIL_STRONG_INT_H_