// 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
