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