// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TOOLS_CLANG_SPANIFY_TESTS_CHROME_BASE_MEMORY_RAW_PTR_H_
#define TOOLS_CLANG_SPANIFY_TESTS_CHROME_BASE_MEMORY_RAW_PTR_H_

#include <cstddef>

namespace base {

// No-op mock traits. Only used to support trait utterances that would
// be necessary in real code.
enum class RawPtrTraits : unsigned {
  kEmpty = 0,
  kAllowPtrArithmetic = (1 << 3),
};

template <typename T, RawPtrTraits PointerTraits = RawPtrTraits::kEmpty>
class raw_ptr {
 public:
  raw_ptr() {}

  raw_ptr(T* data) : data_(data) {}

  operator T*() const { return data_; }

  constexpr T* operator->() const { return data_; }

  T& operator[](int n) { return data_[n]; }

  constexpr raw_ptr& operator++() {
    data_++;
    return *this;
  }

  constexpr raw_ptr operator++(int /* post_increment */) {
    raw_ptr result = *this;
    ++(*this);
    return result;
  }

  constexpr raw_ptr& operator+=(int delta_elems) {
    data_ += delta_elems;
    return *this;
  }

  friend constexpr raw_ptr operator+(const raw_ptr& p, int delta_elems) {
    T* data = p.data_ + delta_elems;
    return data;
  }

  constexpr T& operator*() const { return *data_; }

  T* get() { return data_; }

  constexpr explicit operator bool() const { return !!data_; }

  friend bool operator==(const raw_ptr& lhs, std::nullptr_t) {
    return lhs.data_ == nullptr;
  }
  friend bool operator!=(const raw_ptr& lhs, std::nullptr_t) {
    return lhs.data_ != nullptr;
  }
  friend bool operator==(std::nullptr_t, const raw_ptr& rhs) {
    return nullptr == rhs.data_;
  }
  friend bool operator!=(std::nullptr_t, const raw_ptr& rhs) {
    return nullptr != rhs.data_;
  }

 private:
  T* data_;
};

}  // namespace base

using base::raw_ptr;

// Real-life users of `RawPtrTraits` should not use the qualified
// variants directly, but the bubbled-up aliases.
constexpr inline auto AllowPtrArithmetic =
    base::RawPtrTraits::kAllowPtrArithmetic;

#endif  // TOOLS_CLANG_SPANIFY_TESTS_CHROME_BASE_MEMORY_RAW_PTR_H_
