diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index b5dc473a7..181d113d5 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(fmt)
+add_subdirectory(gsl)
add_subdirectory(glad)
add_subdirectory(stb)
add_subdirectory(zlib)
diff --git a/dep/gsl/CMakeLists.txt b/dep/gsl/CMakeLists.txt
new file mode 100644
index 000000000..462cca37b
--- /dev/null
+++ b/dep/gsl/CMakeLists.txt
@@ -0,0 +1,49 @@
+cmake_minimum_required(VERSION 3.1.3...3.16)
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
+include(guidelineSupportLibrary)
+
+project(GSL
+ VERSION 4.0.0
+ LANGUAGES CXX
+)
+
+# Must include after the project call due to GNUInstallDirs requiring a language be enabled (IE. CXX)
+include(GNUInstallDirs)
+
+# Creates a library GSL which is an interface (header files only)
+add_library(GSL INTERFACE)
+
+# NOTE: If you want to use GSL prefer to link against GSL using this alias target
+# EX:
+# target_link_libraries(foobar PRIVATE Microsoft.GSL::GSL)
+#
+# Add Microsoft.GSL::GSL alias for GSL so that dependents can be agnostic about
+# whether GSL was added via `add_subdirectory` or `find_package`
+add_library(Microsoft.GSL::GSL ALIAS GSL)
+
+# Determine whether this is a standalone project or included by other projects
+set(GSL_STANDALONE_PROJECT OFF)
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ set(GSL_STANDALONE_PROJECT ON)
+endif()
+
+### Project options
+option(GSL_INSTALL "Generate and install GSL target" ${GSL_STANDALONE_PROJECT})
+option(GSL_TEST "Build and perform GSL tests" ${GSL_STANDALONE_PROJECT})
+
+# This GSL implementation generally assumes a platform that implements C++14 support.
+set(gsl_min_cxx_standard "14")
+
+if (GSL_STANDALONE_PROJECT)
+ gsl_set_default_cxx_standard(${gsl_min_cxx_standard})
+else()
+ gsl_client_set_cxx_standard(${gsl_min_cxx_standard})
+endif()
+
+# Setup include directory
+add_subdirectory(include)
+
+# Add natvis file
+gsl_add_native_visualizer_support()
+
diff --git a/dep/gsl/GSL.natvis b/dep/gsl/GSL.natvis
new file mode 100644
index 000000000..1bf27a5c5
--- /dev/null
+++ b/dep/gsl/GSL.natvis
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+ {_Data._What,nasb}
+
+
+
+
+ {{ invoke = {invoke_}, action = {f_} }}
+
+ - invoke_
+ - f_
+
+
+
+
+ {{ extent = {storage_.size_} }}
+
+
+ storage_.size_
+ storage_.data_
+
+
+
+
+
+ {span_.storage_.data_,[span_.storage_.size_]na}
+
+ - span_.storage_.size_
+
+ span_.storage_.size_
+ span_.storage_.data_
+
+
+
+
+
+ {span_.storage_.data_,[span_.storage_.size_]na}
+
+ - span_.storage_.size_
+
+ span_.storage_.size_
+ span_.storage_.data_
+
+
+
+
+
+
+
+ value = {*ptr_}
+
+
diff --git a/dep/gsl/LICENSE b/dep/gsl/LICENSE
new file mode 100644
index 000000000..aa58667a3
--- /dev/null
+++ b/dep/gsl/LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+
+This code is licensed under the MIT License (MIT).
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/dep/gsl/cmake/guidelineSupportLibrary.cmake b/dep/gsl/cmake/guidelineSupportLibrary.cmake
new file mode 100644
index 000000000..b3e00928c
--- /dev/null
+++ b/dep/gsl/cmake/guidelineSupportLibrary.cmake
@@ -0,0 +1,85 @@
+# This cmake module is meant to hold helper functions/macros
+# that make maintaining the cmake build system much easier.
+# This is especially helpful since gsl needs to provide coverage
+# for multiple versions of cmake.
+#
+# Any functions/macros should have a gsl_* prefix to avoid problems
+if (CMAKE_VERSION VERSION_GREATER 3.10 OR CMAKE_VERSION VERSION_EQUAL 3.10)
+ include_guard()
+else()
+ if (DEFINED guideline_support_library_include_guard)
+ return()
+ endif()
+ set(guideline_support_library_include_guard ON)
+endif()
+
+# Necessary for 'write_basic_package_version_file'
+include(CMakePackageConfigHelpers)
+
+function(gsl_set_default_cxx_standard min_cxx_standard)
+ set(GSL_CXX_STANDARD "${min_cxx_standard}" CACHE STRING "Use c++ standard")
+
+ set(GSL_CXX_STD "cxx_std_${GSL_CXX_STANDARD}")
+
+ if (MSVC)
+ set(GSL_CXX_STD_OPT "-std:c++${GSL_CXX_STANDARD}")
+ else()
+ set(GSL_CXX_STD_OPT "-std=c++${GSL_CXX_STANDARD}")
+ endif()
+
+ # when minimum version required is 3.8.0 remove if below
+ # both branches do exactly the same thing
+ if (CMAKE_VERSION VERSION_LESS 3.7.9)
+ include(CheckCXXCompilerFlag)
+ CHECK_CXX_COMPILER_FLAG("${GSL_CXX_STD_OPT}" COMPILER_SUPPORTS_CXX_STANDARD)
+
+ if(COMPILER_SUPPORTS_CXX_STANDARD)
+ target_compile_options(GSL INTERFACE "${GSL_CXX_STD_OPT}")
+ else()
+ message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no c++${GSL_CXX_STANDARD} support. Please use a different C++ compiler.")
+ endif()
+ else()
+ target_compile_features(GSL INTERFACE "${GSL_CXX_STD}")
+ # on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+ endif()
+endfunction()
+
+# The best way for a project to specify the GSL's C++ standard is by the client specifying
+# the CMAKE_CXX_STANDARD. However, this isn't always ideal. Since the CMAKE_CXX_STANDARD is
+# tied to the cmake version. And many projects have low cmake minimums.
+#
+# So provide an alternative approach in case that doesn't work.
+function(gsl_client_set_cxx_standard min_cxx_standard)
+ if (DEFINED CMAKE_CXX_STANDARD)
+ if (${CMAKE_CXX_STANDARD} VERSION_LESS ${min_cxx_standard})
+ message(FATAL_ERROR "GSL: Requires at least CXX standard ${min_cxx_standard}, user provided ${CMAKE_CXX_STANDARD}")
+ endif()
+
+ # Set the GSL standard to what the client desires
+ set(GSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}" PARENT_SCOPE)
+
+ # Exit out early to avoid extra unneccessary work
+ return()
+ endif()
+
+ # Otherwise pick a reasonable default
+ gsl_set_default_cxx_standard(${min_cxx_standard})
+endfunction()
+
+# Adding the GSL.natvis files improves the debugging experience for users of this library.
+function(gsl_add_native_visualizer_support)
+ if (CMAKE_VERSION VERSION_GREATER 3.7.8)
+ if (MSVC_IDE)
+ option(GSL_VS_ADD_NATIVE_VISUALIZERS "Configure project to use Visual Studio native visualizers" TRUE)
+ else()
+ set(GSL_VS_ADD_NATIVE_VISUALIZERS FALSE CACHE INTERNAL "Native visualizers are Visual Studio extension" FORCE)
+ endif()
+
+ # add natvis file to the library so it will automatically be loaded into Visual Studio
+ if(GSL_VS_ADD_NATIVE_VISUALIZERS)
+ target_sources(GSL INTERFACE $)
+ endif()
+ endif()
+endfunction()
+
diff --git a/dep/gsl/include/CMakeLists.txt b/dep/gsl/include/CMakeLists.txt
new file mode 100644
index 000000000..ab90344ca
--- /dev/null
+++ b/dep/gsl/include/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+# Add include folders to the library and targets that consume it
+# the SYSTEM keyword suppresses warnings for users of the library
+#
+# By adding this directory as an include directory the user gets a
+# namespace effect.
+#
+# IE:
+# #include
+if(GSL_STANDALONE_PROJECT)
+ target_include_directories(GSL INTERFACE
+ $
+ $
+ )
+else()
+ target_include_directories(GSL SYSTEM INTERFACE
+ $
+ $
+ )
+endif()
diff --git a/dep/gsl/include/gsl/algorithm b/dep/gsl/include/gsl/algorithm
new file mode 100644
index 000000000..b27475de5
--- /dev/null
+++ b/dep/gsl/include/gsl/algorithm
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_ALGORITHM_H
+#define GSL_ALGORITHM_H
+
+#include // for Expects
+#include // for dynamic_extent, span
+
+#include // for copy_n
+#include // for ptrdiff_t
+#include // for is_assignable
+
+#ifdef _MSC_VER
+#pragma warning(push)
+
+// turn off some warnings that are noisy about our Expects statements
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning(disable : 4996) // unsafe use of std::copy_n
+
+#endif // _MSC_VER
+
+namespace gsl
+{
+// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
+// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
+template
+void copy(span src, span dest)
+{
+ static_assert(std::is_assignable::value,
+ "Elements of source span can not be assigned to elements of destination span");
+ static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
+ (SrcExtent <= DestExtent),
+ "Source range is longer than target range");
+
+ Expects(dest.size() >= src.size());
+ // clang-format off
+ GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
+ // clang-format on
+ std::copy_n(src.data(), src.size(), dest.data());
+}
+
+} // namespace gsl
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#endif // GSL_ALGORITHM_H
diff --git a/dep/gsl/include/gsl/assert b/dep/gsl/include/gsl/assert
new file mode 100644
index 000000000..a6012048f
--- /dev/null
+++ b/dep/gsl/include/gsl/assert
@@ -0,0 +1,136 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_CONTRACTS_H
+#define GSL_CONTRACTS_H
+
+//
+// Temporary until MSVC STL supports no-exceptions mode.
+// Currently terminate is a no-op in this mode, so we add termination behavior back
+//
+#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
+#define GSL_KERNEL_MODE
+
+#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
+#include
+#define RANGE_CHECKS_FAILURE 0
+
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winvalid-noreturn"
+#endif // defined(__clang__)
+
+#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
+ // !_HAS_EXCEPTIONS))
+
+#include
+
+#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
+ // !_HAS_EXCEPTIONS))
+
+//
+// make suppress attributes parse for some compilers
+// Hopefully temporary until suppression standardization occurs
+//
+#if defined(__clang__)
+#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
+#else
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
+#else
+#define GSL_SUPPRESS(x)
+#endif // _MSC_VER
+#endif // __clang__
+
+#define GSL_STRINGIFY_DETAIL(x) #x
+#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
+
+#if defined(__clang__) || defined(__GNUC__)
+#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
+#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
+
+#else
+
+#define GSL_LIKELY(x) (!!(x))
+#define GSL_UNLIKELY(x) (!!(x))
+#endif // defined(__clang__) || defined(__GNUC__)
+
+//
+// GSL_ASSUME(cond)
+//
+// Tell the optimizer that the predicate cond must hold. It is unspecified
+// whether or not cond is actually evaluated.
+//
+#ifdef _MSC_VER
+#define GSL_ASSUME(cond) __assume(cond)
+#elif defined(__GNUC__)
+#define GSL_ASSUME(cond) ((cond) ? static_cast(0) : __builtin_unreachable())
+#else
+#define GSL_ASSUME(cond) static_cast((cond) ? 0 : 0)
+#endif
+
+//
+// GSL.assert: assertions
+//
+
+namespace gsl
+{
+
+namespace details
+{
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+
+ typedef void(__cdecl* terminate_handler)();
+
+ // clang-format off
+ GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
+ // clang-format on
+ [[noreturn]] inline void __cdecl default_terminate_handler()
+ {
+ __fastfail(RANGE_CHECKS_FAILURE);
+ }
+
+ inline gsl::details::terminate_handler& get_terminate_handler() noexcept
+ {
+ static terminate_handler handler = &default_terminate_handler;
+ return handler;
+ }
+
+#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+
+ [[noreturn]] inline void terminate() noexcept
+ {
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+ (*gsl::details::get_terminate_handler())();
+#else
+ std::terminate();
+#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
+ }
+
+} // namespace details
+} // namespace gsl
+
+#define GSL_CONTRACT_CHECK(type, cond) \
+ (GSL_LIKELY(cond) ? static_cast(0) : gsl::details::terminate())
+
+#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
+#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
+
+#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+#endif // GSL_CONTRACTS_H
diff --git a/dep/gsl/include/gsl/byte b/dep/gsl/include/gsl/byte
new file mode 100644
index 000000000..9231340b5
--- /dev/null
+++ b/dep/gsl/include/gsl/byte
@@ -0,0 +1,213 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_BYTE_H
+#define GSL_BYTE_H
+
+//
+// make suppress attributes work for some compilers
+// Hopefully temporary until suppression standardization occurs
+//
+#if defined(__clang__)
+#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
+#else
+#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
+#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
+#else
+#define GSL_SUPPRESS(x)
+#endif // _MSC_VER
+#endif // __clang__
+
+#include
+
+// VS2017 15.8 added support for the __cpp_lib_byte definition
+// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
+#ifdef _MSC_VER
+
+#pragma warning(push)
+
+// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
+#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates
+ // does not always work
+
+#ifndef GSL_USE_STD_BYTE
+// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
+#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \
+ (defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
+
+#define GSL_USE_STD_BYTE 1
+
+#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
+ // 201603)
+
+#define GSL_USE_STD_BYTE 0
+
+#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
+ // 201603)
+#endif // GSL_USE_STD_BYTE
+
+#else // _MSC_VER
+
+#ifndef GSL_USE_STD_BYTE
+#include /* __cpp_lib_byte */
+// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte
+// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte
+#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
+ (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
+ defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
+
+#define GSL_USE_STD_BYTE 1
+
+#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
+ // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
+ // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
+
+#define GSL_USE_STD_BYTE 0
+
+#endif // defined(__cplusplus) && (__cplusplus >= 201703L) &&
+ // (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
+ // defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
+#endif // GSL_USE_STD_BYTE
+
+#endif // _MSC_VER
+
+// Use __may_alias__ attribute on gcc and clang
+#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
+#define byte_may_alias __attribute__((__may_alias__))
+#else // defined __clang__ || defined __GNUC__
+#define byte_may_alias
+#endif // defined __clang__ || defined __GNUC__
+
+#if GSL_USE_STD_BYTE
+#include
+#endif
+
+namespace gsl
+{
+#if GSL_USE_STD_BYTE
+
+using std::byte;
+using std::to_integer;
+
+#else // GSL_USE_STD_BYTE
+
+// This is a simple definition for now that allows
+// use of byte within span<> to be standards-compliant
+enum class byte_may_alias byte : unsigned char
+{
+};
+
+template ::value>>
+constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
+{
+ return b = byte(static_cast(b) << shift);
+}
+
+template ::value>>
+constexpr byte operator<<(byte b, IntegerType shift) noexcept
+{
+ return byte(static_cast(b) << shift);
+}
+
+template ::value>>
+constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
+{
+ return b = byte(static_cast(b) >> shift);
+}
+
+template ::value>>
+constexpr byte operator>>(byte b, IntegerType shift) noexcept
+{
+ return byte(static_cast(b) >> shift);
+}
+
+constexpr byte& operator|=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) | static_cast(r));
+}
+
+constexpr byte operator|(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) | static_cast(r));
+}
+
+constexpr byte& operator&=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) & static_cast(r));
+}
+
+constexpr byte operator&(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) & static_cast(r));
+}
+
+constexpr byte& operator^=(byte& l, byte r) noexcept
+{
+ return l = byte(static_cast(l) ^ static_cast(r));
+}
+
+constexpr byte operator^(byte l, byte r) noexcept
+{
+ return byte(static_cast(l) ^ static_cast(r));
+}
+
+constexpr byte operator~(byte b) noexcept { return byte(~static_cast(b)); }
+
+template ::value>>
+constexpr IntegerType to_integer(byte b) noexcept
+{
+ return static_cast(b);
+}
+
+#endif // GSL_USE_STD_BYTE
+
+template
+constexpr byte to_byte_impl(T t) noexcept
+{
+ static_assert(
+ E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
+ "If you are calling to_byte with an integer contant use: gsl::to_byte() version.");
+ return static_cast(t);
+}
+template <>
+// NOTE: need suppression since c++14 does not allow "return {t}"
+// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
+constexpr byte to_byte_impl(unsigned char t) noexcept
+{
+ return byte(t);
+}
+
+template
+constexpr byte to_byte(T t) noexcept
+{
+ return to_byte_impl::value, T>(t);
+}
+
+template
+constexpr byte to_byte() noexcept
+{
+ static_assert(I >= 0 && I <= 255,
+ "gsl::byte only has 8 bits of storage, values must be in range 0-255");
+ return static_cast(I);
+}
+
+} // namespace gsl
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif // _MSC_VER
+
+#endif // GSL_BYTE_H
diff --git a/dep/gsl/include/gsl/gsl b/dep/gsl/include/gsl/gsl
new file mode 100644
index 000000000..adadc40fe
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_GSL_H
+#define GSL_GSL_H
+
+#include // copy
+#include // Ensures/Expects
+#include // byte
+#include // owner, not_null
+#include // span
+#include // zstring, string_span, zstring_builder...
+#include // finally()/narrow_cast()...
+
+#ifdef __cpp_exceptions
+#include // narrow()
+#endif
+
+#endif // GSL_GSL_H
diff --git a/dep/gsl/include/gsl/gsl_algorithm b/dep/gsl/include/gsl/gsl_algorithm
new file mode 100644
index 000000000..8a88a59b2
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl_algorithm
@@ -0,0 +1,4 @@
+#pragma once
+#pragma message( \
+ "This header will soon be removed. Use instead of ")
+#include
diff --git a/dep/gsl/include/gsl/gsl_assert b/dep/gsl/include/gsl/gsl_assert
new file mode 100644
index 000000000..1dd24b1b3
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl_assert
@@ -0,0 +1,3 @@
+#pragma once
+#pragma message("This header will soon be removed. Use instead of ")
+#include
diff --git a/dep/gsl/include/gsl/gsl_byte b/dep/gsl/include/gsl/gsl_byte
new file mode 100644
index 000000000..b41f2d9a4
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl_byte
@@ -0,0 +1,3 @@
+#pragma once
+#pragma message("This header will soon be removed. Use instead of ")
+#include
diff --git a/dep/gsl/include/gsl/gsl_narrow b/dep/gsl/include/gsl/gsl_narrow
new file mode 100644
index 000000000..d30d42128
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl_narrow
@@ -0,0 +1,3 @@
+#pragma once
+#pragma message("This header will soon be removed. Use instead of ")
+#include
diff --git a/dep/gsl/include/gsl/gsl_util b/dep/gsl/include/gsl/gsl_util
new file mode 100644
index 000000000..feb19902c
--- /dev/null
+++ b/dep/gsl/include/gsl/gsl_util
@@ -0,0 +1,3 @@
+#pragma once
+#pragma message("This header will soon be removed. Use instead of ")
+#include
diff --git a/dep/gsl/include/gsl/narrow b/dep/gsl/include/gsl/narrow
new file mode 100644
index 000000000..ac341ec8c
--- /dev/null
+++ b/dep/gsl/include/gsl/narrow
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_NARROW_H
+#define GSL_NARROW_H
+#include // for Expects
+#include // for narrow_cast
+namespace gsl
+{
+struct narrowing_error : public std::exception
+{
+ const char* what() const noexcept override { return "narrowing_error"; }
+};
+
+// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
+template ::value>::type* = nullptr>
+// clang-format off
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
+ // clang-format on
+ constexpr T narrow(U u) noexcept(false)
+{
+ constexpr const bool is_different_signedness =
+ (std::is_signed::value != std::is_signed::value);
+
+GSL_SUPPRESS(es.103) // NO-FORMAT: attribute // don't overflow
+GSL_SUPPRESS(es.104) // NO-FORMAT: attribute // don't underflow
+GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior
+ const T t = narrow_cast(u); // While this is technically undefined behavior in some cases (i.e., if the source value is of floating-point type
+ // and cannot fit into the destination integral type), the resultant behavior is benign on the platforms
+ // that we target (i.e., no hardware trap representations are hit).
+
+ if (static_cast(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
+ {
+ throw narrowing_error{};
+ }
+
+ return t;
+}
+
+template ::value>::type* = nullptr>
+// clang-format off
+GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
+GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
+ // clang-format on
+ constexpr T narrow(U u) noexcept(false)
+{
+ const T t = narrow_cast(u);
+
+ if (static_cast(t) != u)
+ {
+ throw narrowing_error{};
+ }
+
+ return t;
+}
+} // namespace gsl
+#endif // GSL_NARROW_H
diff --git a/dep/gsl/include/gsl/pointers b/dep/gsl/include/gsl/pointers
new file mode 100644
index 000000000..e6b234853
--- /dev/null
+++ b/dep/gsl/include/gsl/pointers
@@ -0,0 +1,323 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_POINTERS_H
+#define GSL_POINTERS_H
+
+#include // for Ensures, Expects
+
+#include // for forward
+#include // for ptrdiff_t, nullptr_t, size_t
+#include // for shared_ptr, unique_ptr
+#include // for hash
+#include // for enable_if_t, is_convertible, is_assignable
+
+#if !defined(GSL_NO_IOSTREAMS)
+#include // for ostream
+#endif // !defined(GSL_NO_IOSTREAMS)
+
+namespace gsl
+{
+
+namespace details
+{
+ template
+ struct is_comparable_to_nullptr : std::false_type
+ {
+ };
+
+ template
+ struct is_comparable_to_nullptr<
+ T,
+ std::enable_if_t() != nullptr), bool>::value>>
+ : std::true_type
+ {
+ };
+} // namespace details
+
+//
+// GSL.owner: ownership pointers
+//
+using std::shared_ptr;
+using std::unique_ptr;
+
+//
+// owner
+//
+// owner is designed as a bridge for code that must deal directly with owning pointers for some
+// reason
+//
+// T must be a pointer type
+// - disallow construction from any type other than pointer type
+//
+template ::value>>
+using owner = T;
+
+//
+// not_null
+//
+// Restricts a pointer or smart pointer to only hold non-null values.
+//
+// Has zero size overhead over T.
+//
+// If T is a pointer (i.e. T == U*) then
+// - allow construction from U*
+// - disallow construction from nullptr_t
+// - disallow default construction
+// - ensure construction from null U* fails
+// - allow implicit conversion to U*
+//
+template
+class not_null
+{
+public:
+ static_assert(details::is_comparable_to_nullptr::value, "T cannot be compared to nullptr.");
+
+ template ::value>>
+ constexpr not_null(U&& u) : ptr_(std::forward(u))
+ {
+ Expects(ptr_ != nullptr);
+ }
+
+ template ::value>>
+ constexpr not_null(T u) : ptr_(std::move(u))
+ {
+ Expects(ptr_ != nullptr);
+ }
+
+ template ::value>>
+ constexpr not_null(const not_null& other) : not_null(other.get())
+ {}
+
+ not_null(const not_null& other) = default;
+ not_null& operator=(const not_null& other) = default;
+ constexpr std::conditional_t::value, T, const T&> get() const
+ {
+ Ensures(ptr_ != nullptr);
+ return ptr_;
+ }
+
+ constexpr operator T() const { return get(); }
+ constexpr decltype(auto) operator->() const { return get(); }
+ constexpr decltype(auto) operator*() const { return *get(); }
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ not_null(std::nullptr_t) = delete;
+ not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ not_null& operator++() = delete;
+ not_null& operator--() = delete;
+ not_null operator++(int) = delete;
+ not_null operator--(int) = delete;
+ not_null& operator+=(std::ptrdiff_t) = delete;
+ not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+
+private:
+ T ptr_;
+};
+
+template
+auto make_not_null(T&& t) noexcept
+{
+ return not_null>>{std::forward(t)};
+}
+
+#if !defined(GSL_NO_IOSTREAMS)
+template
+std::ostream& operator<<(std::ostream& os, const not_null& val)
+{
+ os << val.get();
+ return os;
+}
+#endif // !defined(GSL_NO_IOSTREAMS)
+
+template
+auto operator==(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() == rhs.get()))
+ -> decltype(lhs.get() == rhs.get())
+{
+ return lhs.get() == rhs.get();
+}
+
+template
+auto operator!=(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() != rhs.get()))
+ -> decltype(lhs.get() != rhs.get())
+{
+ return lhs.get() != rhs.get();
+}
+
+template
+auto operator<(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() < rhs.get()))
+ -> decltype(lhs.get() < rhs.get())
+{
+ return lhs.get() < rhs.get();
+}
+
+template
+auto operator<=(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() <= rhs.get()))
+ -> decltype(lhs.get() <= rhs.get())
+{
+ return lhs.get() <= rhs.get();
+}
+
+template
+auto operator>(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() > rhs.get()))
+ -> decltype(lhs.get() > rhs.get())
+{
+ return lhs.get() > rhs.get();
+}
+
+template
+auto operator>=(const not_null& lhs,
+ const not_null& rhs) noexcept(noexcept(lhs.get() >= rhs.get()))
+ -> decltype(lhs.get() >= rhs.get())
+{
+ return lhs.get() >= rhs.get();
+}
+
+// more unwanted operators
+template
+std::ptrdiff_t operator-(const not_null&, const not_null&) = delete;
+template
+not_null operator-(const not_null&, std::ptrdiff_t) = delete;
+template
+not_null operator+(const not_null&, std::ptrdiff_t) = delete;
+template
+not_null operator+(std::ptrdiff_t, const not_null&) = delete;
+
+} // namespace gsl
+
+namespace std
+{
+template
+struct hash>
+{
+ std::size_t operator()(const gsl::not_null& value) const { return hash{}(value.get()); }
+};
+
+} // namespace std
+
+namespace gsl
+{
+
+//
+// strict_not_null
+//
+// Restricts a pointer or smart pointer to only hold non-null values,
+//
+// - provides a strict (i.e. explicit constructor from T) wrapper of not_null
+// - to be used for new code that wishes the design to be cleaner and make not_null
+// checks intentional, or in old code that would like to make the transition.
+//
+// To make the transition from not_null, incrementally replace not_null
+// by strict_not_null and fix compilation errors
+//
+// Expect to
+// - remove all unneeded conversions from raw pointer to not_null and back
+// - make API clear by specifying not_null in parameters where needed
+// - remove unnecessary asserts
+//
+template
+class strict_not_null : public not_null
+{
+public:
+ template ::value>>
+ constexpr explicit strict_not_null(U&& u) : not_null(std::forward(u))
+ {}
+
+ template ::value>>
+ constexpr explicit strict_not_null(T u) : not_null(u)
+ {}
+
+ template ::value>>
+ constexpr strict_not_null(const not_null& other) : not_null(other)
+ {}
+
+ template ::value>>
+ constexpr strict_not_null(const strict_not_null& other) : not_null(other)
+ {}
+
+ strict_not_null(strict_not_null&& other) = default;
+ strict_not_null(const strict_not_null& other) = default;
+ strict_not_null& operator=(const strict_not_null& other) = default;
+ strict_not_null& operator=(const not_null& other)
+ {
+ not_null::operator=(other);
+ return *this;
+ }
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ strict_not_null(std::nullptr_t) = delete;
+ strict_not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ strict_not_null& operator++() = delete;
+ strict_not_null& operator--() = delete;
+ strict_not_null operator++(int) = delete;
+ strict_not_null operator--(int) = delete;
+ strict_not_null& operator+=(std::ptrdiff_t) = delete;
+ strict_not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+};
+
+// more unwanted operators
+template
+std::ptrdiff_t operator-(const strict_not_null&, const strict_not_null&) = delete;
+template
+strict_not_null operator-(const strict_not_null&, std::ptrdiff_t) = delete;
+template
+strict_not_null operator+(const strict_not_null&, std::ptrdiff_t) = delete;
+template
+strict_not_null operator+(std::ptrdiff_t, const strict_not_null&) = delete;
+
+template
+auto make_strict_not_null(T&& t) noexcept
+{
+ return strict_not_null>>{std::forward(t)};
+}
+
+#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
+
+// deduction guides to prevent the ctad-maybe-unsupported warning
+template
+not_null(T) -> not_null;
+template
+strict_not_null(T) -> strict_not_null;
+
+#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
+
+} // namespace gsl
+
+namespace std
+{
+template
+struct hash>
+{
+ std::size_t operator()(const gsl::strict_not_null& value) const
+ {
+ return hash{}(value.get());
+ }
+};
+
+} // namespace std
+
+#endif // GSL_POINTERS_H
diff --git a/dep/gsl/include/gsl/span b/dep/gsl/include/gsl/span
new file mode 100644
index 000000000..cc8a7b9b0
--- /dev/null
+++ b/dep/gsl/include/gsl/span
@@ -0,0 +1,821 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
+//
+// This code is licensed under the MIT License (MIT).
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef GSL_SPAN_H
+#define GSL_SPAN_H
+
+#include // for Expects
+#include // for byte
+#include // for narrow_cast
+
+#include // for array
+#include // for ptrdiff_t, size_t, nullptr_t
+#include // for span specialization of gsl::at and other span-related extensions
+#include // for reverse_iterator, distance, random_access_...
+#include // for enable_if_t, declval, is_convertible, inte...
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(push)
+
+// turn off some warnings that are noisy about our Expects statements
+#pragma warning(disable : 4127) // conditional expression is constant
+#pragma warning( \
+ disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
+#pragma warning(disable : 4702) // unreachable code
+
+// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
+#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
+#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
+
+#endif // _MSC_VER
+
+// See if we have enough C++17 power to use a static constexpr data member
+// without needing an out-of-line definition
+#if !(defined(__cplusplus) && (__cplusplus >= 201703L))
+#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
+#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
+
+// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
+// While there is a conversion from signed to unsigned, it happens at
+// compiletime, so the compiler wouldn't have to warn indiscriminately, but
+// could check if the source value actually doesn't fit into the target type
+// and only warn in those cases.
+#if defined(__GNUC__) && __GNUC__ > 6
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif
+
+namespace gsl
+{
+
+// implementation details
+namespace details
+{
+ template
+ struct is_span_oracle : std::false_type
+ {
+ };
+
+ template
+ struct is_span_oracle> : std::true_type
+ {
+ };
+
+ template
+ struct is_span : public is_span_oracle>
+ {
+ };
+
+ template
+ struct is_std_array_oracle : std::false_type
+ {
+ };
+
+ template
+ struct is_std_array_oracle> : std::true_type
+ {
+ };
+
+ template
+ struct is_std_array : is_std_array_oracle>
+ {
+ };
+
+ template
+ struct is_allowed_extent_conversion
+ : std::integral_constant
+ {
+ };
+
+ template
+ struct is_allowed_element_type_conversion
+ : std::integral_constant::value>
+ {
+ };
+
+ template
+ class span_iterator
+ {
+ public:
+ using iterator_category = std::random_access_iterator_tag;
+ using value_type = std::remove_cv_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = Type*;
+ using reference = Type&;
+
+#ifdef _MSC_VER
+ using _Unchecked_type = pointer;
+#endif // _MSC_VER
+ constexpr span_iterator() = default;
+
+ constexpr span_iterator(pointer begin, pointer end, pointer current)
+ : begin_(begin), end_(end), current_(current)
+ {}
+
+ constexpr operator span_iterator() const noexcept
+ {
+ return {begin_, end_, current_};
+ }
+
+ constexpr reference operator*() const noexcept
+ {
+ Expects(begin_ && end_);
+ Expects(begin_ <= current_ && current_ < end_);
+ return *current_;
+ }
+
+ constexpr pointer operator->() const noexcept
+ {
+ Expects(begin_ && end_);
+ Expects(begin_ <= current_ && current_ < end_);
+ return current_;
+ }
+ constexpr span_iterator& operator++() noexcept
+ {
+ Expects(begin_ && current_ && end_);
+ Expects(current_ < end_);
+ // clang-format off
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ // clang-format on
+ ++current_;
+ return *this;
+ }
+
+ constexpr span_iterator operator++(int) noexcept
+ {
+ span_iterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ constexpr span_iterator& operator--() noexcept
+ {
+ Expects(begin_ && end_);
+ Expects(begin_ < current_);
+ --current_;
+ return *this;
+ }
+
+ constexpr span_iterator operator--(int) noexcept
+ {
+ span_iterator ret = *this;
+ --*this;
+ return ret;
+ }
+
+ constexpr span_iterator& operator+=(const difference_type n) noexcept
+ {
+ if (n != 0) Expects(begin_ && current_ && end_);
+ if (n > 0) Expects(end_ - current_ >= n);
+ if (n < 0) Expects(current_ - begin_ >= -n);
+ // clang-format off
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ // clang-format on
+ current_ += n;
+ return *this;
+ }
+
+ constexpr span_iterator operator+(const difference_type n) const noexcept
+ {
+ span_iterator ret = *this;
+ ret += n;
+ return ret;
+ }
+
+ friend constexpr span_iterator operator+(const difference_type n,
+ const span_iterator& rhs) noexcept
+ {
+ return rhs + n;
+ }
+
+ constexpr span_iterator& operator-=(const difference_type n) noexcept
+ {
+ if (n != 0) Expects(begin_ && current_ && end_);
+ if (n > 0) Expects(current_ - begin_ >= n);
+ if (n < 0) Expects(end_ - current_ >= -n);
+ current_ -= n;
+ return *this;
+ }
+
+ constexpr span_iterator operator-(const difference_type n) const noexcept
+ {
+ span_iterator ret = *this;
+ ret -= n;
+ return ret;
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr difference_type operator-(const span_iterator& rhs) const noexcept
+ {
+ Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
+ return current_ - rhs.current_;
+ }
+
+ constexpr reference operator[](const difference_type n) const noexcept
+ {
+ return *(*this + n);
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator==(const span_iterator& rhs) const noexcept
+ {
+ Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
+ return current_ == rhs.current_;
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator!=(const span_iterator& rhs) const noexcept
+ {
+ return !(*this == rhs);
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator<(const span_iterator& rhs) const noexcept
+ {
+ Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
+ return current_ < rhs.current_;
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator>(const span_iterator& rhs) const noexcept
+ {
+ return rhs < *this;
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator<=(const span_iterator& rhs) const noexcept
+ {
+ return !(rhs < *this);
+ }
+
+ template <
+ class Type2,
+ std::enable_if_t, value_type>::value, int> = 0>
+ constexpr bool operator>=(const span_iterator& rhs) const noexcept
+ {
+ return !(*this < rhs);
+ }
+
+#ifdef _MSC_VER
+ // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
+ // to unwrap span_iterator to a pointer type after a range check in STL
+ // algorithm calls
+ friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
+ { // test that [lhs, rhs) forms a valid range inside an STL algorithm
+ Expects(lhs.begin_ == rhs.begin_ // range spans have to match
+ && lhs.end_ == rhs.end_ &&
+ lhs.current_ <= rhs.current_); // range must not be transposed
+ }
+
+ constexpr void _Verify_offset(const difference_type n) const noexcept
+ { // test that *this + n is within the range of this call
+ if (n != 0) Expects(begin_ && current_ && end_);
+ if (n > 0) Expects(end_ - current_ >= n);
+ if (n < 0) Expects(current_ - begin_ >= -n);
+ }
+
+ // clang-format off
+ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
+ // clang-format on
+ constexpr pointer _Unwrapped() const noexcept
+ { // after seeking *this to a high water mark, or using one of the
+ // _Verify_xxx functions above, unwrap this span_iterator to a raw
+ // pointer
+ return current_;
+ }
+
+ // Tell the STL that span_iterator should not be unwrapped if it can't
+ // validate in advance, even in release / optimized builds:
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const bool _Unwrap_when_unverified = false;
+#else
+ static constexpr bool _Unwrap_when_unverified = false;
+#endif
+ // clang-format off
+ GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
+ // clang-format on
+ constexpr void _Seek_to(const pointer p) noexcept
+ { // adjust the position of *this to previously verified location p
+ // after _Unwrapped
+ current_ = p;
+ }
+#endif
+
+ pointer begin_ = nullptr;
+ pointer end_ = nullptr;
+ pointer current_ = nullptr;
+ };
+
+ template
+ class extent_type
+ {
+ public:
+ using size_type = std::size_t;
+
+ constexpr extent_type() noexcept = default;
+
+ constexpr explicit extent_type(extent_type);
+
+ constexpr explicit extent_type(size_type size) { Expects(size == Ext); }
+
+ constexpr size_type size() const noexcept { return Ext; }
+
+ private:
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const size_type size_ = Ext; // static size equal to Ext
+#else
+ static constexpr size_type size_ = Ext; // static size equal to Ext
+#endif
+ };
+
+ template <>
+ class extent_type
+ {
+ public:
+ using size_type = std::size_t;
+
+ template
+ constexpr explicit extent_type(extent_type ext) : size_(ext.size())
+ {}
+
+ constexpr explicit extent_type(size_type size) : size_(size)
+ {
+ Expects(size != dynamic_extent);
+ }
+
+ constexpr size_type size() const noexcept { return size_; }
+
+ private:
+ size_type size_;
+ };
+
+ template
+ constexpr extent_type::extent_type(extent_type ext)
+ {
+ Expects(ext.size() == Ext);
+ }
+
+ template
+ struct calculate_subspan_type
+ {
+ using type = span;
+ };
+} // namespace details
+
+// [span], class template span
+template
+class span
+{
+public:
+ // constants and types
+ using element_type = ElementType;
+ using value_type = std::remove_cv_t;
+ using size_type = std::size_t;
+ using pointer = element_type*;
+ using const_pointer = const element_type*;
+ using reference = element_type&;
+ using const_reference = const element_type&;
+ using difference_type = std::ptrdiff_t;
+
+ using iterator = details::span_iterator;
+ using reverse_iterator = std::reverse_iterator;
+
+#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
+ static constexpr const size_type extent{Extent};
+#else
+ static constexpr size_type extent{Extent};
+#endif
+
+ // [span.cons], span constructors, copy, assignment, and destructor
+ template " SFINAE, since "std::enable_if_t" is ill-formed when Extent is greater than 0.
+ class = std::enable_if_t<(Dependent ||
+ details::is_allowed_extent_conversion<0, Extent>::value)>>
+ constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
+ {}
+
+ template = 0>
+ constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
+ {
+ Expects(count == Extent);
+ }
+
+ template = 0>
+ constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
+ {}
+
+ template = 0>
+ constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
+ : storage_(firstElem, narrow_cast(lastElem - firstElem))
+ {
+ Expects(lastElem - firstElem == static_cast(Extent));
+ }
+
+ template = 0>
+ constexpr span(pointer firstElem, pointer lastElem) noexcept
+ : storage_(firstElem, narrow_cast(lastElem - firstElem))
+ {}
+
+ template ::value, int> = 0>
+ constexpr span(element_type (&arr)[N]) noexcept
+ : storage_(KnownNotNull{arr}, details::extent_type())
+ {}
+
+ template <
+ class T, std::size_t N,
+ std::enable_if_t<(details::is_allowed_extent_conversion::value &&
+ details::is_allowed_element_type_conversion::value),
+ int> = 0>
+ constexpr span(std::array& arr) noexcept
+ : storage_(KnownNotNull{arr.data()}, details::extent_type())
+ {}
+
+ template ::value &&
+ details::is_allowed_element_type_conversion::value),
+ int> = 0>
+ constexpr span(const std::array