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

// This is Chromium's base/containers/span.h, modified to support C++17
// as part of the PDFium project, stubbed to be self-contained, and then
// modified to conform to ANGLE:
//  -- fixed missing constexpr as exercised by test.
//  -- added operator==().

#ifndef COMMON_SPAN_H_
#define COMMON_SPAN_H_

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <array>
#include <functional>
#include <iterator>
#include <memory>
#include <new>
#include <optional>
#include <type_traits>
#include <utility>

#include "common/base/anglebase/logging.h"
#include "common/unsafe_buffers.h"

namespace angle
{

constexpr size_t dynamic_extent = static_cast<size_t>(-1);

template <typename T>
using DefaultSpanInternalPtr = T *;

template <typename T,
          size_t Extent        = dynamic_extent,
          typename InternalPtr = DefaultSpanInternalPtr<T>>
class Span;

namespace internal
{

template <typename T>
struct IsSpanImpl : std::false_type
{};

template <typename T>
struct IsSpanImpl<Span<T>> : std::true_type
{};

template <typename T>
using IsSpan = IsSpanImpl<typename std::decay<T>::type>;

template <typename T>
struct IsStdArrayImpl : std::false_type
{};

template <typename T, size_t N>
struct IsStdArrayImpl<std::array<T, N>> : std::true_type
{};

template <typename T>
using IsStdArray = IsStdArrayImpl<typename std::decay<T>::type>;

template <typename From, typename To>
using IsLegalSpanConversion = std::is_convertible<From *, To *>;

template <typename Container, typename T>
using ContainerHasConvertibleData = IsLegalSpanConversion<
    typename std::remove_pointer<decltype(std::declval<Container>().data())>::type,
    T>;
template <typename Container>
using ContainerHasIntegralSize = std::is_integral<decltype(std::declval<Container>().size())>;

template <typename From, typename To>
using EnableIfLegalSpanConversion =
    typename std::enable_if<IsLegalSpanConversion<From, To>::value>::type;

// SFINAE check if Container can be converted to a Span<T>. Note that the
// implementation details of this check differ slightly from the requirements in
// the working group proposal: in particular, the proposal also requires that
// the container conversion constructor participate in overload resolution only
// if two additional conditions are true:
//
//   1. Container implements operator[].
//   2. Container::value_type matches remove_const_t<element_type>.
//
// The requirements are relaxed slightly here: in particular, not requiring (2)
// means that an immutable Span can be easily constructed from a mutable
// container.
template <typename Container, typename T>
using EnableIfSpanCompatibleContainer =
    typename std::enable_if<!internal::IsSpan<Container>::value &&
                            !internal::IsStdArray<Container>::value &&
                            ContainerHasConvertibleData<Container, T>::value &&
                            ContainerHasIntegralSize<Container>::value>::type;

template <typename Container, typename T>
using EnableIfConstSpanCompatibleContainer =
    typename std::enable_if<std::is_const<T>::value && !internal::IsSpan<Container>::value &&
                            !internal::IsStdArray<Container>::value &&
                            ContainerHasConvertibleData<Container, T>::value &&
                            ContainerHasIntegralSize<Container>::value>::type;

}  // namespace internal

// A Span is a value type that represents an array of elements of type T. Since
// it only consists of a pointer to memory with an associated size, it is very
// light-weight. It is cheap to construct, copy, move and use spans, so that
// users are encouraged to use it as a pass-by-value parameter. A Span does not
// own the underlying memory, so care must be taken to ensure that a Span does
// not outlive the backing store.
//
// Differences from the working group proposal
// -------------------------------------------
//
// https://wg21.link/P0122 is the latest working group proposal, Chromium
// currently implements R6.
//
// Differences in constants and types:
// - Span has a capital "S".
// - Allows custom smart pointer types in internal representation, if desired.
// - no element_type type alias
// - no index_type type alias
// - no different_type type alias
// - no extent constant
//
// Differences from [span.cons]:
// - no constructor from a pointer range
//
// Differences from [span.sub]:
// - using size_t instead of ptrdiff_t for indexing
//
// Differences from [span.obs]:
// - using size_t instead of ptrdiff_t to represent size()
//
// Differences from [span.elem]:
// - no operator ()()
// - using size_t instead of ptrdiff_t for indexing
//
// Additions beyond the C++ standard draft
// - as_chars() function.
// - as_writable_chars() function.
// - as_byte_span() function.
// - as_writable_byte_span() function.
// - span_from_ref() function.
// - byte_span_from_ref() function.

// [span], class template span
template <typename T, size_t Extent, typename InternalPtr>
class Span
{
  public:
    using value_type             = typename std::remove_cv<T>::type;
    using pointer                = T *;
    using reference              = T &;
    using iterator               = T *;
    using const_iterator         = const T *;
    using reverse_iterator       = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    // [span.cons], span constructors, copy, assignment, and destructor
    constexpr Span() noexcept = default;

    ANGLE_UNSAFE_BUFFER_USAGE constexpr Span(T *data, size_t size) noexcept
        : data_(data), size_(size)
    {
        DCHECK(data_ || size_ == 0);
    }

    // TODO(dcheng): Implement construction from a |begin| and |end| pointer.
    template <size_t N>
    constexpr Span(T (&array)[N]) noexcept
        // SAFETY: The type signature guarantees `array` contains `N` elements.
        : ANGLE_UNSAFE_BUFFERS(Span(array, N))
    {
        static_assert(Extent == dynamic_extent || Extent == N);
    }

    template <size_t N>
    constexpr Span(std::array<T, N> &array) noexcept
        // SAFETY: The type signature guarantees `array` contains `N` elements.
        : ANGLE_UNSAFE_BUFFERS(Span(array.data(), N))
    {
        static_assert(Extent == dynamic_extent || Extent == N);
    }

    template <typename U, size_t N, typename = std::enable_if_t<std::is_convertible_v<U *, T *>>>
    constexpr Span(const std::array<U, N> &array) noexcept
        // SAFETY: The type signature guarantees `array` contains `N` elements.
        : ANGLE_UNSAFE_BUFFERS(Span(array.data(), N))
    {
        static_assert(Extent == dynamic_extent || Extent == N);
    }

    // Conversion from a container that provides |T* data()| and |integral_type
    // size()|. Note that |data()| may not return nullptr for some empty
    // containers, which can lead to container overflow errors when probing
    // raw ptrs.
    template <typename Container,
              typename = internal::EnableIfSpanCompatibleContainer<Container, T>>
    constexpr Span(Container &container)
        // SAFETY: `size()` is the number of elements that can be safely accessed
        // at `data()`.
        : ANGLE_UNSAFE_BUFFERS(Span(container.data(), container.size()))
    {}

    template <typename Container,
              typename = internal::EnableIfConstSpanCompatibleContainer<Container, T>>
    constexpr Span(const Container &container)
        // SAFETY: `size()` is exactly the number of elements in the initializer
        // list, so accessing that many will be safe.
        : ANGLE_UNSAFE_BUFFERS(Span(container.data(), container.size()))
    {}

    constexpr Span(const Span &other) noexcept = default;

    // Conversions from spans of compatible types: this allows a Span<T> to be
    // seamlessly used as a Span<const T>, but not the other way around.
    template <typename U,
              size_t M,
              typename R,
              typename = internal::EnableIfLegalSpanConversion<U, T>>
    constexpr Span(const Span<U, M, R> &other)
        // SAFETY: `size()` is the number of elements that can be safely accessed
        // at `data()`.
        : ANGLE_UNSAFE_BUFFERS(Span(other.data(), other.size()))
    {
        static_assert(Extent == dynamic_extent || Extent == M,
                      "Assigning to fixed span from incompatible span");
    }

    Span &operator=(const Span &other) noexcept = default;
    Span &operator=(Span &&other) noexcept      = default;

    ~Span() noexcept = default;

    template <typename U, size_t M>
    bool operator==(const Span<U, M> &other) const
    {
        return std::equal(begin(), end(), other.begin(), other.end());
    }
    template <typename U, size_t M>
    bool operator!=(const Span<U, M> &other) const
    {
        return !std::equal(begin(), end(), other.begin(), other.end());
    }

    // Performs a deep copy of the elements referenced by `other` to those
    // referenced by `this`. The spans must be the same size.
    // (Not in `std::`; inspired by Rust's `slice::copy_from_slice()`.)
    template <typename U,
              size_t M,
              typename R,
              typename V = T,
              typename   = std::enable_if_t<
                    !std::is_const<V>::value && std::is_convertible<U *, const T *>::value &&
                    (Extent == dynamic_extent || M == dynamic_extent || M == Extent)>>
    void copy_from(const Span<U, M, R> &other) const
    {
        CHECK(size() == other.size());
        if (std::less_equal<const void *>{}(data(), other.data()))
        {
            std::copy(other.begin(), other.end(), begin());
        }
        else
        {
            std::copy_backward(other.begin(), other.end(), end());
        }
    }

    template <typename Container,
              typename V = T,
              typename   = internal::EnableIfSpanCompatibleContainer<Container, V>,
              typename   = std::enable_if_t<!std::is_const<V>::value>>
    void copy_from(const Container &container) const
    {
        copy_from(Span<const T, Extent>(container));
    }

    template <size_t N>
    constexpr std::optional<Span<T, N>> to_fixed_extent() const
    {
        return (size() == N)
                   ? std::optional<Span<T, N>>(ANGLE_UNSAFE_BUFFERS(Span<T, N>(data(), N)))
                   : std::nullopt;
    }

    template <size_t Offset,
              typename = std::enable_if_t<(Extent == dynamic_extent || Offset <= Extent)>>
    constexpr auto split_at() const
    {
        CHECK(Offset <= size());
        return std::make_pair(first<Offset>(), subspan<Offset>());
    }

    constexpr auto split_at(size_t offset) const
    {
        CHECK(offset <= size());
        return std::make_pair(first(offset), subspan(offset));
    }

    // [span.sub], span subviews
    template <size_t Count>
    constexpr Span<T, Count> first() const
    {
        // TODO(tsepez): The following assert isn't yet good enough to replace
        // the runtime check since we are still allowing unchecked conversions
        // to arbitrary non-dynamic_extent spans.
        static_assert(Extent == dynamic_extent || Count <= Extent);
        CHECK(Count <= size_);
        // SAFETY: CHECK() on line above.
        return ANGLE_UNSAFE_BUFFERS(Span<T, Count>(data(), Count));
    }
    constexpr Span<T, dynamic_extent> first(size_t count) const
    {
        CHECK(count <= size_);
        // SAFETY: CHECK() on line above.
        return ANGLE_UNSAFE_BUFFERS(Span(static_cast<T *>(data_), count));
    }

    template <size_t Count>
    constexpr Span<T, Count> last() const
    {
        // TODO(tsepez): The following assert isn't yet good enough to replace
        // the runtime check since we are still allowing unchecked conversions
        // to arbitrary non-dynamic_extent spans.
        static_assert(Extent == dynamic_extent || Count <= Extent);
        CHECK(Count <= size_);
        // SAFETY: CHECK() on line above.
        return ANGLE_UNSAFE_BUFFERS(Span<T, Count>(data() + (size_ - Count), Count));
    }
    constexpr Span<T, dynamic_extent> last(size_t count) const
    {
        CHECK(count <= size_);
        // SAFETY: CHECK() on line above.
        return ANGLE_UNSAFE_BUFFERS(Span(static_cast<T *>(data_) + (size_ - count), count));
    }

    template <size_t Offset, size_t Count = dynamic_extent>
    constexpr Span<T, dynamic_extent> subspan() const
    {
        // TODO(tsepez): The following check isn't yet good enough to replace
        // the runtime check since we are still allowing unchecked conversions
        // to arbitrary non-dynamic_extent spans.
        static_assert(Extent == dynamic_extent || Count == dynamic_extent ||
                      Offset + Count <= Extent);
        return subspan(Offset, Count);
    }
    constexpr Span<T, dynamic_extent> subspan(size_t pos, size_t count = dynamic_extent) const
    {
        CHECK(pos <= size_);
        CHECK(count == dynamic_extent || count <= size_ - pos);
        // SAFETY: CHECK()s on lines above.
        return ANGLE_UNSAFE_BUFFERS(
            Span(static_cast<T *>(data_) + pos, count == dynamic_extent ? size_ - pos : count));
    }

    // [span.obs], span observers
    constexpr size_t size() const noexcept { return size_; }
    constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); }
    constexpr bool empty() const noexcept { return size_ == 0; }

    // [span.elem], span element access
    constexpr T &operator[](size_t index) const noexcept
    {
        CHECK(index < size_);
        return ANGLE_UNSAFE_BUFFERS(static_cast<T *>(data_)[index]);
    }

    constexpr T &front() const noexcept
    {
        CHECK(!empty());
        return *data();
    }

    constexpr T &back() const noexcept
    {
        CHECK(!empty());
        return ANGLE_UNSAFE_BUFFERS(*(data() + size() - 1));
    }

    constexpr T *data() const noexcept { return static_cast<T *>(data_); }

    // [span.iter], span iterator support
    constexpr iterator begin() const noexcept { return static_cast<T *>(data_); }
    constexpr iterator end() const noexcept { return ANGLE_UNSAFE_BUFFERS(begin() + size_); }

    constexpr const_iterator cbegin() const noexcept { return begin(); }
    constexpr const_iterator cend() const noexcept { return end(); }

    constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
    constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }

    constexpr const_reverse_iterator crbegin() const noexcept
    {
        return const_reverse_iterator(cend());
    }
    constexpr const_reverse_iterator crend() const noexcept
    {
        return const_reverse_iterator(cbegin());
    }

  private:
    InternalPtr data_ = nullptr;
    size_t size_      = 0;
};

// Deduction guides.
template <typename T, size_t N>
Span(T (&)[N]) -> Span<T, N>;

template <typename T, size_t N>
Span(const T (&)[N]) -> Span<const T, N>;

template <typename T, size_t N>
Span(std::array<T, N> &) -> Span<T, N>;

template <typename T, size_t N>
Span(const std::array<T, N> &) -> Span<const T, N>;

template <typename Container,
          typename = internal::EnableIfSpanCompatibleContainer<
              Container,
              std::remove_pointer_t<decltype(std::declval<Container>().data())>>>
Span(Container &&) -> Span<std::remove_pointer_t<decltype(std::declval<Container>().data())>>;

// [span.objectrep], views of object representation
template <typename T, size_t N, typename P>
Span<const uint8_t> as_bytes(Span<T, N, P> s) noexcept
{
    // SAFETY: from size_bytes() method.
    return ANGLE_UNSAFE_BUFFERS(
        Span<const uint8_t>(reinterpret_cast<const uint8_t *>(s.data()), s.size_bytes()));
}

template <typename T,
          size_t N,
          typename P,
          typename U = typename std::enable_if<!std::is_const<T>::value>::type>
Span<uint8_t> as_writable_bytes(Span<T, N, P> s) noexcept
{
    // SAFETY: from size_bytes() method.
    return ANGLE_UNSAFE_BUFFERS(
        Span<uint8_t>(reinterpret_cast<uint8_t *>(s.data()), s.size_bytes()));
}

template <typename T, size_t N, typename P>
Span<const char> as_chars(Span<T, N, P> s) noexcept
{
    // SAFETY: from size_bytes() method.
    return ANGLE_UNSAFE_BUFFERS(
        Span<const char>(reinterpret_cast<const char *>(s.data()), s.size_bytes()));
}

template <typename T,
          size_t N,
          typename P,
          typename U = typename std::enable_if<!std::is_const<T>::value>::type>
Span<char> as_writable_chars(Span<T, N, P> s) noexcept
{
    // SAFETY: from size_bytes() method.
    return ANGLE_UNSAFE_BUFFERS(Span<char>(reinterpret_cast<char *>(s.data()), s.size_bytes()));
}

// `span_from_ref` converts a reference to T into a span of length 1.  This is a
// non-std helper that is inspired by the `std::slice::from_ref()` function from
// Rust.
template <typename T>
static constexpr Span<T> span_from_ref(T &single_object) noexcept
{
    // SAFETY: single object passed by reference.
    return ANGLE_UNSAFE_BUFFERS(Span<T>(&single_object, 1u));
}

// `byte_span_from_ref` converts a reference to T into a span of uint8_t of
// length sizeof(T).  This is a non-std helper that is a sugar for
// `as_writable_bytes(span_from_ref(x))`.
template <typename T>
static constexpr Span<const uint8_t> byte_span_from_ref(const T &single_object) noexcept
{
    return as_bytes(span_from_ref(single_object));
}
template <typename T>
static constexpr Span<uint8_t> byte_span_from_ref(T &single_object) noexcept
{
    return as_writable_bytes(span_from_ref(single_object));
}

// Convenience function for converting an object which is itself convertible
// to span into a span of bytes (i.e. span of const uint8_t). Typically used
// to convert std::string or string-objects holding chars, or std::vector
// or vector-like objects holding other scalar types, prior to passing them
// into an API that requires byte spans.
template <typename T>
Span<const uint8_t> as_byte_span(const T &arg)
{
    return as_bytes(Span(arg));
}
template <typename T>
Span<const uint8_t> as_byte_span(T &&arg)
{
    return as_bytes(Span(arg));
}

// Convenience function for converting an object which is itself convertible
// to span into a span of mutable bytes (i.e. span of uint8_t). Typically used
// to convert std::string or string-objects holding chars, or std::vector
// or vector-like objects holding other scalar types, prior to passing them
// into an API that requires mutable byte spans.
template <typename T>
constexpr Span<uint8_t> as_writable_byte_span(T &&arg)
{
    return as_writable_bytes(Span(arg));
}

template <typename ElementType, typename ByteType, size_t Extent, typename InternalPtr>
    requires(std::same_as<std::remove_cv_t<ByteType>, uint8_t> &&
             std::is_trivially_copyable_v<ElementType> &&
             (!std::is_const_v<ByteType> || std::is_const_v<ElementType>) &&
             (Extent == dynamic_extent || Extent % sizeof(ElementType) == 0))
[[nodiscard]] constexpr auto reinterpret_span(Span<ByteType, Extent, InternalPtr> span)
{
    CHECK(reinterpret_cast<uintptr_t>(span.data()) % alignof(ElementType) == 0u);
    if constexpr (Extent == dynamic_extent)
    {
        CHECK(span.size_bytes() % sizeof(ElementType) == 0u);
    }
    ElementType *ptr = std::launder(reinterpret_cast<ElementType *>(span.data()));
    if constexpr (Extent == dynamic_extent)
    {
        // SAFETY: We checked for proper alignment, size, strict aliasing rules, and
        // started the lifetime of the array.
        return ANGLE_UNSAFE_BUFFERS(
            Span<ElementType, dynamic_extent>(ptr, span.size_bytes() / sizeof(ElementType)));
    }
    else
    {
        // SAFETY: We checked for proper alignment, size, strict aliasing rules, and
        // started the lifetime of the array.
        constexpr size_t NewCount = Extent / sizeof(ElementType);
        return ANGLE_UNSAFE_BUFFERS(Span<ElementType, NewCount>(ptr, NewCount));
    }
}

}  // namespace angle

#endif  // COMMON_SPAN_H_
