// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT

/**
 * @file Pointer utilities
 */

#pragma once

#include <cheri.hh>
#include <concepts>

namespace ds::pointer
{

	/**
	 * Offset a pointer by a number of bytes.  The return type must be
	 * explicitly specified by the caller.  The type of the displacement offset
	 * (Offset) is templated so that we can accept both signed and unsigned
	 * offsets.
	 */
	template<typename T, typename U>
	static inline __always_inline T *offset(U *base, std::integral auto offset)
	{
		CHERI::Capability c{base};
		c.address() += offset;
		return c.template cast<void>().template cast<T>();
	}

	/**
	 * Compute the unsigned difference in bytes between two pointers' target
	 * addresses.  To be standards-compliant, cursor must be part of the same
	 * allocation as base and at a higher address.
	 */
	static inline __always_inline size_t diff(const void *base,
	                                          const void *cursor)
	{
		return static_cast<size_t>(reinterpret_cast<const char *>(cursor) -
		                           reinterpret_cast<const char *>(base));
	}

	namespace proxy
	{

		/**
		 * Proxies<P,T> if P is a proxy object for T*-s.
		 */
		template<typename P, typename T>
		concept Proxies = std::same_as<T, typename P::Type> &&
		                  requires(P &proxy, P &proxy2, T *ptr) {
			                  /* Probe for operator=(T*) */
			                  {
				                  proxy = ptr
			                  } -> std::same_as<P &>;

			                  /* Probe for operator T*() */
			                  {
				                  ptr == proxy
			                  } -> std::same_as<bool>;

			                  /* TODO: How to probe for operator-> ? */

			                  /* Probe for operator==(T*) */
			                  {
				                  proxy == ptr
			                  } -> std::same_as<bool>;

			                  /* Probe for operator==(P&) */
			                  {
				                  proxy == proxy2
			                  } -> std::same_as<bool>;

			                  /* Probe for operator<=>(T*) */
			                  {
				                  proxy <=> ptr
			                  } -> std::same_as<std::strong_ordering>;

			                  /* Probe for operator<=>(P) */
			                  {
				                  proxy <=> proxy2
			                  } -> std::same_as<std::strong_ordering>;
		                  };

		/**
		 * Pointer references are pointer proxies, shockingly enough.
		 */
		template<typename T>
		class Pointer
		{
			T *&ref;

			public:
			using Type = T;

			__always_inline Pointer(T *&r) : ref(r) {}

			__always_inline operator T *()
			{
				return ref;
			}

			__always_inline T *operator->()
			{
				return *this;
			}

			__always_inline Pointer<T> &operator=(T *t)
			{
				ref = t;
				return *this;
			}

			__always_inline Pointer<T> &operator=(Pointer const &p)
			{
				ref = p.ref;
				return *this;
			}

			__always_inline bool operator==(Pointer &p)
			{
				return this->ref == p.ref;
			}

			__always_inline auto operator<=>(Pointer &p)
			{
				return this->ref <=> p.ref;
			}
		};
		static_assert(Proxies<Pointer<void>, void>);

		/**
		 * Equipped with a context for bounds, an address reference can be a
		 * proxy for a pointer.
		 */
		template<typename T>
		class PtrAddr
		{
			CHERI::Capability<void> ctx;
			ptraddr_t              &ref;

			public:
			using Type = T;

			__always_inline PtrAddr(void *c, ptraddr_t &r) : ctx(c), ref(r) {}

			__always_inline operator T *()
			{
				auto c      = ctx;
				c.address() = ref;
				return c.cast<T>().get();
			}

			__always_inline T *operator->()
			{
				return *this;
			}

			__always_inline PtrAddr &operator=(T *p)
			{
				ref = CHERI::Capability{p}.address();
				return *this;
			}

			__always_inline PtrAddr &operator=(PtrAddr const &p)
			{
				ref = p.ref;
				return *this;
			}

			/*
			 * Since the context is used only for bounds, don't bother
			 * implicitly converting both proxies up to T*
			 */

			__always_inline bool operator==(PtrAddr &p)
			{
				return ref == p.ref;
			}

			__always_inline auto operator<=>(PtrAddr &p)
			{
				return ref <=> p.ref;
			}
		};
		static_assert(Proxies<PtrAddr<void>, void>);

		/**
		 * Deduction gude for the common enough case where the context
		 * type and the represented type are equal.
		 */
		template<typename T>
		PtrAddr(T *, ptraddr_t) -> PtrAddr<T>;

		/**
		 * Like the above, but with a constant offset on the interpretation of
		 * its addresss fields.  This is useful for building points-to-container
		 * data structures (rather than points-to-member as with the above two).
		 * The container_of and address-taking operations that move back and
		 * forth between container and link member should fuse away with the
		 * offsetting operations herein.  You may prefer this if your common or
		 * fast-paths involve lots of container_of operations.
		 */
		template<ptrdiff_t Offset, typename T>
		class OffsetPtrAddr
		{
			CHERI::Capability<void> ctx;
			ptraddr_t              &ref;

			public:
			using Type = T;

			__always_inline OffsetPtrAddr(void *c, ptraddr_t &r)
			  : ctx(c), ref(r)
			{
			}

			__always_inline operator T *()
			{
				auto c      = ctx;
				c.address() = ref + Offset;
				return c.cast<T>().get();
			}

			__always_inline T *operator->()
			{
				return *this;
			}

			__always_inline OffsetPtrAddr &operator=(T *p)
			{
				ref = CHERI::Capability{p}.address() - Offset;
				return *this;
			}

			__always_inline OffsetPtrAddr &operator=(OffsetPtrAddr const &p)
			{
				ref = p.ref;
				return *this;
			}

			/*
			 * Since the context is used only for bounds, don't bother
			 * implicitly converting both proxies up to T*.  This also probably
			 * saves the optimizer the effort of cancelling the Offset
			 * arithmetic on either side of the comparison.
			 */

			__always_inline bool operator==(OffsetPtrAddr &p)
			{
				return ref == p.ref;
			}

			__always_inline auto operator<=>(OffsetPtrAddr &p)
			{
				return ref <=> p.ref;
			}
		};
		static_assert(Proxies<OffsetPtrAddr<8, void>, void>);

	} // namespace proxy

} // namespace ds::pointer
