Repository: skyline-emu/skyline
File: app/src/main/cpp/skyline/common.h (C/C++)

Code before:
            std::reverse(in.begin(), in.end());
            return in;
        }

        constexpr u64 SwapEndianness(u64 in) {
            return __builtin_bswap64(in);
        }

        constexpr u32 SwapEndianness(u32 in) {
            return __builtin_bswap32(in);
        }

        constexpr u16 SwapEndianness(u16 in) {
            return __builtin_bswap16(in);
        }

        /**
         * @brief A compile-time hash function as std::hash isn't constexpr
         */
        constexpr std::size_t Hash(std::string_view view) {
            return frz::elsa<frz::string>{}(frz::string(view.data(), view.size()), 0);
        }
    }

    /**
     * @brief A custom wrapper over span that adds several useful methods to it
     * @note This class is completely transparent, it implicitly converts from and to span
     */
    template<typename T, size_t Extent = std::dynamic_extent>
    class span : public std::span<T, Extent> {
      public:
        using std::span<T, Extent>::span;
        using std::span<T, Extent>::operator=;

        typedef typename std::span<T, Extent>::element_type element_type;
        typedef typename std::span<T, Extent>::size_type size_type;

        constexpr span(const std::span<T, Extent> &spn) : std::span<T, Extent>(spn) {}

        /**
         * @brief We want to support implicitly casting from std::string_view -> span as it's just a specialization of a data view which span is a generic form of, the opposite doesn't hold true as not all data held by a span is string data therefore the conversion isn't implicit there
         */
        template<typename Traits>
        constexpr span(const std::basic_string_view<T, Traits> &string) : std::span<T, Extent>(const_cast<T *>(string.data()), string.size()) {}

        template<typename Out>
        constexpr Out &as() {
            if (span::size_bytes() >= sizeof(Out))
                return *reinterpret_cast<Out *>(span::data());
            throw exception("Span size is less than Out type size (0x{:X}/0x{:X})", span::size_bytes(), sizeof(Out));
        }

Review comment (suggestion):
I'd actually recommend changing this a bit and naming it `PointerFor` (also change `type` to a pointer type) and explicitly stating that it selects the largest possible pointer type for representing an object alongside providing the size of the object in terms of the underlying type.

Code after:
        constexpr std::array<u8, N> SwapEndianness(std::array<u8, N> in) {
            std::reverse(in.begin(), in.end());
            return in;
        }

        constexpr u64 SwapEndianness(u64 in) {
            return __builtin_bswap64(in);
        }

        constexpr u32 SwapEndianness(u32 in) {
            return __builtin_bswap32(in);
        }

        constexpr u16 SwapEndianness(u16 in) {
            return __builtin_bswap16(in);
        }

        /**
         * @brief A compile-time hash function as std::hash isn't constexpr
         */
        constexpr std::size_t Hash(std::string_view view) {
            return frz::elsa<frz::string>{}(frz::string(view.data(), view.size()), 0);
        }

        /**
         * @brief Selects the largest possible integer type for representing an object alongside providing the size of the object in terms of the underlying type
         */
        template<class T>
        struct IntegerFor {
            using type = std::conditional_t<sizeof(T) % sizeof(u64) == 0, u64,
                std::conditional_t<sizeof(T) % sizeof(u32) == 0, u32,
                    std::conditional_t<sizeof(T) % sizeof(u16) == 0, u16, u8>
                >
            >;

            static constexpr size_t count{sizeof(T) / sizeof(type)};
        };

        namespace detail {
            static thread_local std::mt19937_64 generator{GetTimeTicks()};
        }

        /**
         * @brief Fills an array with random data from a Mersenne Twister pseudo-random generator
         * @note The generator is seeded with the the current time in ticks
         */
        template<typename T> requires (std::is_integral_v<T>)
        void FillRandomBytes(std::span<T> in) {
            std::independent_bits_engine<std::mt19937_64, std::numeric_limits<T>::digits, T> gen(detail::generator);

            std::generate(in.begin(), in.end(), gen);