[
  {
    "path": ".clang-format",
    "content": "BasedOnStyle: Google\nIndentWidth: 2\nUseTab: Never\nColumnLimit: 0\nNamespaceIndentation: None\nBreakBeforeBraces: Attach\nAllowShortFunctionsOnASingleLine: Inline\nReflowComments: true\n"
  },
  {
    "path": ".github/workflows/bigendiancmake.yml",
    "content": "name: CMake on s390x emulation (Big endian system)\n\non: [push, pull_request]\n\nenv:\n  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)\n  BUILD_TYPE: RelWithDebInfo\n\njobs:\n  build-linux-s390x:\n    # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.\n    runs-on: ubuntu-latest  \n\n    steps:\n    - uses: actions/checkout@v3\n\n    - uses: uraimo/run-on-arch-action@v2\n      name: Run commands\n      id: runcmd\n      with:\n        arch: s390x\n        distro: ubuntu_latest\n        install: |\n          apt-get update -q -y\n          apt-get -y install cmake\n          apt-get -y install make\n          apt-get -y install g++\n          apt-get -y install git\n        run: |\n          lscpu | grep Endian\n          cmake  -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .\n          cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}\n          cd ${{github.workspace}}/build\n          ctest -C ${{env.BUILD_TYPE}} --output-on-failure"
  },
  {
    "path": ".github/workflows/cmake.yml",
    "content": "name: CMake\n\non: [push, pull_request]\n\nenv:\n  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)\n  BUILD_TYPE: RelWithDebInfo\n\njobs:\n  build:\n    # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.\n    strategy:\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n\n    runs-on: ${{ matrix.os }}  \n\n    steps:\n    - uses: actions/checkout@v3\n\n    - name: Install optional tools (clang-tidy)\n      if: matrix.os == 'ubuntu-latest'\n      run: sudo apt-get install -y clang-tidy\n\n    - name: Configure CMake (Windows)\n      if: runner.os == 'Windows'\n      # Configure CMake in a 'build' subdirectory.\n      # `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.\n      # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type\n      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .\n\n    - name: Configure CMake (Other OS)\n      if: runner.os != 'Windows'\n      # Configure CMake in a 'build' subdirectory.\n      # `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.\n      # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type\n      run: cmake -B ${{github.workspace}}/build -USE_ASAN=ON -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} .\n\n    - name: Build\n      # Build your program with the given configuration\n      run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}\n\n    - name: Test\n      working-directory: ${{github.workspace}}/build\n      # Execute tests defined by the CMake configuration.\n      # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail\n      run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure\n\n"
  },
  {
    "path": ".github/workflows/cpplint.yml",
    "content": "# GitHub Action to run cpplint recursively on all pushes and pull requests\n# https://github.com/cpplint/GitHub-Action-for-cpplint\n\nname: cpplint\non: [push, pull_request]\njobs:\n  cpplint:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - uses: actions/setup-python@v4\n      with:\n        python-version: 3.x\n    - run: pip install cpplint\n    - run: cpplint --root=include --recursive .\n"
  },
  {
    "path": ".gitignore",
    "content": "main.cpp\nbuild\n*.user\n*.swp\nscripts/build.sh\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16)\nproject(base64)\n\noption(BASE64_ENABLE_TESTING \"Build test files.\" ON)\n\nset(CMAKE_CXX_STANDARD 17)\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\nif(NOT CMAKE_BUILD_TYPE)\n  set(CMAKE_BUILD_TYPE RelWithDebInfo)\nendif()\n\n# Warnings compiler flags\nif(MSVC)\n  add_compile_options(/W4)\nelse()\n  add_compile_options(-Wall -Wextra -Wpedantic)\nendif()\n\n# Optionally enable clang-tidy\nfind_program(CLANG_TIDY_EXE NAMES clang-tidy PATHS /opt/homebrew/opt/llvm/bin/)\nif(NOT CLANG_TIDY_EXE)\n  message(STATUS \"clang-tidy not found. Skipping corresponding checks.\")\nelse()\n  set(CMAKE_CXX_CLANG_TIDY \n    ${CLANG_TIDY_EXE};\n    -header-filter=.*;\n    -checks=-*,portability-*,bugprone-*,-bugprone-easily-swappable-parameters,-bugprone-sizeof-expression,clang-analyzer-*;\n  )\n  message(STATUS \"Found clang-tidy: ${CLANG_TIDY_EXE}.\")\nendif()\n\n# Simplify the use of ASan\noption(USE_ASAN \"Activate ASan compiler/linker options\" OFF)\nif(USE_ASAN)\n  if(MSVC)\n    add_compile_options(/fsanitize=address)\n    add_link_options(/fsanitize=address)\n    set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT \"$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>\")\n  else()\n    add_compile_options(-fsanitize=address -fno-omit-frame-pointer)\n    add_link_options(-fsanitize=address)\n  endif()\nendif()\n\nadd_library(base64 INTERFACE)\ntarget_include_directories(base64 INTERFACE include)\n\nif (BASE64_ENABLE_TESTING)\n  add_executable(roundtrip_test test/roundtrip_test.cpp)\n  target_link_libraries(roundtrip_test PRIVATE base64)\n\n  enable_testing()\n  add_test(NAME roundtrip_test COMMAND roundtrip_test)\n\n  # Add some more tests\n  include(FetchContent)\n  if(${CMAKE_CXX_BYTE_ORDER} MATCHES BIG_ENDIAN)\n    set(FETCHCONTENT_QUIET FALSE)\n  endif()\n  FetchContent_Declare(\n    googletest\n    GIT_REPOSITORY https://github.com/google/googletest.git\n    GIT_TAG        b514bdc898e2951020cbdca1304b75f5950d1f59\n    GIT_PROGRESS   TRUE\n    SYSTEM\n  )\n  # For Windows: Prevent overriding the parent project's compiler/linker settings\n  set(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\n  FetchContent_MakeAvailable(googletest)\n\n  set_target_properties(gtest PROPERTIES CXX_CLANG_TIDY \"\")\n  set_target_properties(gtest_main PROPERTIES CXX_CLANG_TIDY \"\")\n  set_target_properties(gmock PROPERTIES CXX_CLANG_TIDY \"\")\n  set_target_properties(gmock_main PROPERTIES CXX_CLANG_TIDY \"\")\n\n  add_executable(base64_tests test/base64_tests.cpp)\n  target_link_libraries(base64_tests PRIVATE base64)\n  target_link_libraries(base64_tests PRIVATE GTest::gtest GTest::gtest_main)\n  add_test(NAME base64_tests COMMAND base64_tests)\n\n  add_executable(modp_b64_tests test/modp_b64_tests.cpp)\n  target_link_libraries(modp_b64_tests PRIVATE base64)\n  target_link_libraries(modp_b64_tests PRIVATE GTest::gtest GTest::gtest_main)\n  add_test(NAME modp_b64_tests COMMAND modp_b64_tests)\nendif()\n\n"
  },
  {
    "path": "CPPLINT.cfg",
    "content": "filter=-legal/copyright\nfilter=-readability/todo"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2019 Tobias Locker\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# base64\n\nA simple, header-only C++17 library for Base64 encoding and decoding. Uses modern C++ features when available\n(e.g., `std::bit_cast` in C++20) while remaining portable and efficient.\n\n## Features\n\n- Header-only, single-file library  \n- Fast encoding/decoding using lookup tables  \n- Safe type punning using `std::bit_cast` (avoids undefined behavior with unions)  \n- Throws `std::runtime_error` for invalid Base64 input (size, padding, or characters)  \n\n## Platform Support\n\n- Compilers: GCC, Clang, MSVC  \n- Architectures: x86, x64, ARM, AArch64 (little-endian)  \n- Requires C++17 (C++20 features optional)  \n\n## Usage\n\n```cpp\n#include <iostream>  \n#include \"base64.hpp\"  \n\nint main() {  \n    auto encoded = base64::to_base64(\"Hello, World!\");  \n    std::cout << encoded << std::endl; // SGVsbG8sIFdvcmxkIQ==  \n\n    auto decoded = base64::from_base64(\"SGVsbG8sIFdvcmxkIQ==\");  \n    std::cout << decoded << std::endl; // Hello, World!  \n}\n```\n\n## Notes\n\n- Inspired by Nick Galbreath's modp_b64 (used by Chromium) for high performance  \n- Compatible with C++17; optionally uses C++20 features  \n- Avoids union-based type punning for safety  \n- Faster implementations exist using SIMD or multithreading but are not header-only  \n\n## References\n\n- Benchmark of C/C++ Base64 libraries: https://github.com/gaspardpetit/base64/  \n- Chromium modp_b64: https://github.com/chromium/chromium/tree/main/third_party/modp_b64  \n- SIMD/optimized alternatives:  \n  - https://github.com/aklomp/base64  \n  - https://github.com/simdutf/simdutf  \n  - https://github.com/powturbo/Turbo-Base64\n"
  },
  {
    "path": "include/base64.hpp",
    "content": "#ifndef BASE64_HPP_\n#define BASE64_HPP_\n\n#include <algorithm>\n#include <array>\n#include <cassert>\n#include <cstdint>\n#include <cstring>\n#include <stdexcept>\n#include <string>\n#include <string_view>\n#include <type_traits>\n\n#if defined(__cpp_lib_bit_cast)\n#include <bit>  // For std::bit_cast.\n#endif\n\nnamespace base64 {\n\nnamespace detail {\n\n#if defined(__cpp_lib_bit_cast)\nusing std::bit_cast;\n#else\ntemplate <class To, class From>\nstd::enable_if_t<sizeof(To) == sizeof(From) &&\nstd::is_trivially_copyable_v<From> &&\nstd::is_trivially_copyable_v<To>,\nTo> bit_cast(const From& src) noexcept {\n  static_assert(std::is_trivially_constructible_v<To>,\n                \"This implementation additionally requires \"\n                \"destination type to be trivially constructible\");\n\n  To dst;\n  std::memcpy(&dst, &src, sizeof(To));\n  return dst;\n}\n#endif\n\ninline constexpr char padding_char{'='};\ninline constexpr uint32_t bad_char{0x01FFFFFF};\n\n#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)\n#if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) ||  \\\n    (defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN) ||              \\\n    (defined(_BYTE_ORDER) && _BYTE_ORDER == _BIG_ENDIAN) ||                 \\\n    (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) ||                    \\\n    (defined(__sun) && defined(__SVR4) && defined(_BIG_ENDIAN)) ||          \\\n    defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \\\n    defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__) ||         \\\n    defined(_M_PPC)\n#define __BIG_ENDIAN__\n#elif (defined(__BYTE_ORDER__) &&                                              \\\n       __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || /* gcc */                 \\\n    (defined(__BYTE_ORDER) &&                                                  \\\n     __BYTE_ORDER == __LITTLE_ENDIAN) /* linux header */                       \\\n    || (defined(_BYTE_ORDER) && _BYTE_ORDER == _LITTLE_ENDIAN) ||              \\\n    (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) /* mingw header */ || \\\n    (defined(__sun) && defined(__SVR4) &&                                      \\\n     defined(_LITTLE_ENDIAN)) || /* solaris */                                 \\\n    defined(__ARMEL__) ||                                                      \\\n    defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) ||      \\\n    defined(__MIPSEL) || defined(__MIPSEL__) || defined(_M_IX86) ||            \\\n    defined(_M_X64) || defined(_M_IA64) || /* msvc for intel processors */     \\\n    defined(_M_ARM) ||                                                         \\\n    defined(_M_ARM64) /* msvc code on arm executes in little endian mode */\n#define __LITTLE_ENDIAN__\n#endif\n#endif\n\n#if !defined(__LITTLE_ENDIAN__) & !defined(__BIG_ENDIAN__)\n#error \"UNKNOWN Platform / endianness. Configure endianness explicitly.\"\n#endif\n\n#if defined(__LITTLE_ENDIAN__)\nstd::array<std::uint32_t, 256> constexpr decode_table_0 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,\n    0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,\n    0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,\n    0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,\n    0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,\n    0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,\n    0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,\n    0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,\n    0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,\n    0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,\n    0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_1 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,\n    0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,\n    0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,\n    0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,\n    0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,\n    0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,\n    0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,\n    0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,\n    0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,\n    0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,\n    0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_2 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,\n    0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,\n    0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,\n    0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,\n    0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,\n    0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,\n    0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,\n    0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,\n    0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,\n    0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,\n    0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_3 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,\n    0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,\n    0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,\n    0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,\n    0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,\n    0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,\n    0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,\n    0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,\n    0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,\n    0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,\n    0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\n// TODO fix decoding tables to avoid the need for different indices in big\n// endian?\ninline constexpr size_t decidx0{0};\ninline constexpr size_t decidx1{1};\ninline constexpr size_t decidx2{2};\n\n#elif defined(__BIG_ENDIAN__)\n\nstd::array<std::uint32_t, 256> constexpr decode_table_0 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00f80000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00fc0000,\n    0x00d00000, 0x00d40000, 0x00d80000, 0x00dc0000, 0x00e00000, 0x00e40000,\n    0x00e80000, 0x00ec0000, 0x00f00000, 0x00f40000, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00040000, 0x00080000, 0x000c0000, 0x00100000, 0x00140000, 0x00180000,\n    0x001c0000, 0x00200000, 0x00240000, 0x00280000, 0x002c0000, 0x00300000,\n    0x00340000, 0x00380000, 0x003c0000, 0x00400000, 0x00440000, 0x00480000,\n    0x004c0000, 0x00500000, 0x00540000, 0x00580000, 0x005c0000, 0x00600000,\n    0x00640000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00680000, 0x006c0000, 0x00700000, 0x00740000, 0x00780000,\n    0x007c0000, 0x00800000, 0x00840000, 0x00880000, 0x008c0000, 0x00900000,\n    0x00940000, 0x00980000, 0x009c0000, 0x00a00000, 0x00a40000, 0x00a80000,\n    0x00ac0000, 0x00b00000, 0x00b40000, 0x00b80000, 0x00bc0000, 0x00c00000,\n    0x00c40000, 0x00c80000, 0x00cc0000, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_1 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0003e000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0003f000,\n    0x00034000, 0x00035000, 0x00036000, 0x00037000, 0x00038000, 0x00039000,\n    0x0003a000, 0x0003b000, 0x0003c000, 0x0003d000, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,\n    0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,\n    0x0000d000, 0x0000e000, 0x0000f000, 0x00010000, 0x00011000, 0x00012000,\n    0x00013000, 0x00014000, 0x00015000, 0x00016000, 0x00017000, 0x00018000,\n    0x00019000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0001a000, 0x0001b000, 0x0001c000, 0x0001d000, 0x0001e000,\n    0x0001f000, 0x00020000, 0x00021000, 0x00022000, 0x00023000, 0x00024000,\n    0x00025000, 0x00026000, 0x00027000, 0x00028000, 0x00029000, 0x0002a000,\n    0x0002b000, 0x0002c000, 0x0002d000, 0x0002e000, 0x0002f000, 0x00030000,\n    0x00031000, 0x00032000, 0x00033000, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_2 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00000f80, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000fc0,\n    0x00000d00, 0x00000d40, 0x00000d80, 0x00000dc0, 0x00000e00, 0x00000e40,\n    0x00000e80, 0x00000ec0, 0x00000f00, 0x00000f40, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00000040, 0x00000080, 0x000000c0, 0x00000100, 0x00000140, 0x00000180,\n    0x000001c0, 0x00000200, 0x00000240, 0x00000280, 0x000002c0, 0x00000300,\n    0x00000340, 0x00000380, 0x000003c0, 0x00000400, 0x00000440, 0x00000480,\n    0x000004c0, 0x00000500, 0x00000540, 0x00000580, 0x000005c0, 0x00000600,\n    0x00000640, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x00000680, 0x000006c0, 0x00000700, 0x00000740, 0x00000780,\n    0x000007c0, 0x00000800, 0x00000840, 0x00000880, 0x000008c0, 0x00000900,\n    0x00000940, 0x00000980, 0x000009c0, 0x00000a00, 0x00000a40, 0x00000a80,\n    0x00000ac0, 0x00000b00, 0x00000b40, 0x00000b80, 0x00000bc0, 0x00000c00,\n    0x00000c40, 0x00000c80, 0x00000cc0, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\nstd::array<std::uint32_t, 256> constexpr decode_table_3 = {\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0000003e, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000003f,\n    0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039,\n    0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,\n    0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006,\n    0x00000007, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,\n    0x0000000d, 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, 0x00000012,\n    0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018,\n    0x00000019, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x0000001e,\n    0x0000001f, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024,\n    0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a,\n    0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030,\n    0x00000031, 0x00000032, 0x00000033, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,\n    0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff\n};\n\n// TODO fix decoding tables to avoid the need for different indices in big\n// endian?\ninline constexpr size_t decidx0{1};\ninline constexpr size_t decidx1{2};\ninline constexpr size_t decidx2{3};\n\n#endif\n\nstd::array<char, 256> constexpr encode_table_0 = {\n    'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'D', 'D', 'D',\n    'D', 'E', 'E', 'E', 'E', 'F', 'F', 'F', 'F', 'G', 'G', 'G', 'G', 'H', 'H',\n    'H', 'H', 'I', 'I', 'I', 'I', 'J', 'J', 'J', 'J', 'K', 'K', 'K', 'K', 'L',\n    'L', 'L', 'L', 'M', 'M', 'M', 'M', 'N', 'N', 'N', 'N', 'O', 'O', 'O', 'O',\n    'P', 'P', 'P', 'P', 'Q', 'Q', 'Q', 'Q', 'R', 'R', 'R', 'R', 'S', 'S', 'S',\n    'S', 'T', 'T', 'T', 'T', 'U', 'U', 'U', 'U', 'V', 'V', 'V', 'V', 'W', 'W',\n    'W', 'W', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y', 'Y', 'Z', 'Z', 'Z', 'Z', 'a',\n    'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd',\n    'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g', 'g', 'h', 'h', 'h',\n    'h', 'i', 'i', 'i', 'i', 'j', 'j', 'j', 'j', 'k', 'k', 'k', 'k', 'l', 'l',\n    'l', 'l', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'o', 'p',\n    'p', 'p', 'p', 'q', 'q', 'q', 'q', 'r', 'r', 'r', 'r', 's', 's', 's', 's',\n    't', 't', 't', 't', 'u', 'u', 'u', 'u', 'v', 'v', 'v', 'v', 'w', 'w', 'w',\n    'w', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'z', 'z', 'z', 'z', '0', '0',\n    '0', '0', '1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3', '4',\n    '4', '4', '4', '5', '5', '5', '5', '6', '6', '6', '6', '7', '7', '7', '7',\n    '8', '8', '8', '8', '9', '9', '9', '9', '+', '+', '+', '+', '/', '/', '/',\n    '/'\n};\n\nstd::array<char, 256> constexpr encode_table_1 = {\n    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',\n    'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',\n    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',\n    't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',\n    '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',\n    'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\n    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',\n    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',\n    '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G',\n    'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',\n    'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',\n    'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',\n    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', 'A', 'B', 'C',\n    'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',\n    'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g',\n    'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',\n    'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',\n    '/'\n};\n\n}  // namespace detail\n\ntemplate <class OutputBuffer, class InputIterator>\ninline OutputBuffer encode_into(InputIterator begin, InputIterator end) {\n  typedef std::decay_t<decltype(*begin)> input_value_type;\n  static_assert(std::is_same_v<input_value_type, char> ||\n                std::is_same_v<input_value_type, signed char> ||\n                std::is_same_v<input_value_type, unsigned char> ||\n                std::is_same_v<input_value_type, std::byte>);\n  typedef typename OutputBuffer::value_type output_value_type;\n  static_assert(std::is_same_v<output_value_type, char> ||\n                std::is_same_v<output_value_type, signed char> ||\n                std::is_same_v<output_value_type, unsigned char> ||\n                std::is_same_v<output_value_type, std::byte>);\n  const size_t binarytextsize = end - begin;\n  const size_t encodedsize = (binarytextsize / 3 + (binarytextsize % 3 > 0))\n                             << 2;\n  OutputBuffer encoded(encodedsize, detail::padding_char);\n\n  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&*begin);\n  char* currEncoding = reinterpret_cast<char*>(&encoded[0]);\n\n  for (size_t i = binarytextsize / 3; i; --i) {\n    const uint8_t t1 = *bytes++;\n    const uint8_t t2 = *bytes++;\n    const uint8_t t3 = *bytes++;\n    *currEncoding++ = detail::encode_table_0[t1];\n    *currEncoding++ =\n        detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];\n    *currEncoding++ =\n        detail::encode_table_1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];\n    *currEncoding++ = detail::encode_table_1[t3];\n  }\n\n  switch (binarytextsize % 3) {\n    case 0: {\n      break;\n    }\n    case 1: {\n      const uint8_t t1 = bytes[0];\n      *currEncoding++ = detail::encode_table_0[t1];\n      *currEncoding++ = detail::encode_table_1[(t1 & 0x03) << 4];\n      break;\n    }\n    case 2: {\n      const uint8_t t1 = bytes[0];\n      const uint8_t t2 = bytes[1];\n      *currEncoding++ = detail::encode_table_0[t1];\n      *currEncoding++ =\n          detail::encode_table_1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];\n      *currEncoding++ = detail::encode_table_1[(t2 & 0x0F) << 2];\n      break;\n    }\n    default: {\n      throw std::runtime_error{\"Invalid base64 encoded data\"};\n    }\n  }\n\n  return encoded;\n}\n\ntemplate <class OutputBuffer>\ninline OutputBuffer encode_into(std::string_view data) {\n  return encode_into<OutputBuffer>(std::begin(data), std::end(data));\n}\n\ninline std::string to_base64(std::string_view data) {\n  return encode_into<std::string>(std::begin(data), std::end(data));\n}\n\ntemplate <class OutputBuffer>\ninline OutputBuffer decode_into(std::string_view base64Text) {\n  typedef typename OutputBuffer::value_type output_value_type;\n  static_assert(std::is_same_v<output_value_type, char> ||\n                std::is_same_v<output_value_type, signed char> ||\n                std::is_same_v<output_value_type, unsigned char> ||\n                std::is_same_v<output_value_type, std::byte>);\n  if (base64Text.empty()) {\n    return OutputBuffer();\n  }\n\n  if ((base64Text.size() & 3) != 0) {\n    throw std::runtime_error{\n        \"Invalid base64 encoded data - Size not divisible by 4\"};\n  }\n\n  const size_t numPadding =\n      std::count(base64Text.rbegin(), base64Text.rbegin() + 4, '=');\n  if (numPadding > 2) {\n    throw std::runtime_error{\n        \"Invalid base64 encoded data - Found more than 2 padding signs\"};\n  }\n\n  const size_t decodedsize = (base64Text.size() * 3 >> 2) - numPadding;\n  OutputBuffer decoded(decodedsize, '.');\n\n  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&base64Text[0]);\n  char* currDecoding = reinterpret_cast<char*>(&decoded[0]);\n\n  for (size_t i = (base64Text.size() >> 2) - (numPadding != 0); i; --i) {\n    const uint8_t t1 = *bytes++;\n    const uint8_t t2 = *bytes++;\n    const uint8_t t3 = *bytes++;\n    const uint8_t t4 = *bytes++;\n\n    const uint32_t d1 = detail::decode_table_0[t1];\n    const uint32_t d2 = detail::decode_table_1[t2];\n    const uint32_t d3 = detail::decode_table_2[t3];\n    const uint32_t d4 = detail::decode_table_3[t4];\n\n    const uint32_t temp = d1 | d2 | d3 | d4;\n\n    if (temp >= detail::bad_char) {\n      throw std::runtime_error{\n          \"Invalid base64 encoded data - Invalid character\"};\n    }\n\n    // Use bit_cast instead of union and type punning to avoid\n    // undefined behaviour risk:\n    // https://en.wikipedia.org/wiki/Type_punning#Use_of_union\n    const std::array<char, 4> tempBytes =\n        detail::bit_cast<std::array<char, 4>, uint32_t>(temp);\n\n    *currDecoding++ = tempBytes[detail::decidx0];\n    *currDecoding++ = tempBytes[detail::decidx1];\n    *currDecoding++ = tempBytes[detail::decidx2];\n  }\n\n  switch (numPadding) {\n    case 0: {\n      break;\n    }\n    case 1: {\n      const uint8_t t1 = *bytes++;\n      const uint8_t t2 = *bytes++;\n      const uint8_t t3 = *bytes++;\n\n      const uint32_t d1 = detail::decode_table_0[t1];\n      const uint32_t d2 = detail::decode_table_1[t2];\n      const uint32_t d3 = detail::decode_table_2[t3];\n\n      const uint32_t temp = d1 | d2 | d3;\n\n      if (temp >= detail::bad_char) {\n        throw std::runtime_error{\n            \"Invalid base64 encoded data - Invalid character\"};\n      }\n\n      // Use bit_cast instead of union and type punning to avoid\n      // undefined behaviour risk:\n      // https://en.wikipedia.org/wiki/Type_punning#Use_of_union\n      const std::array<char, 4> tempBytes =\n          detail::bit_cast<std::array<char, 4>, uint32_t>(temp);\n      *currDecoding++ = tempBytes[detail::decidx0];\n      *currDecoding++ = tempBytes[detail::decidx1];\n      break;\n    }\n    case 2: {\n      const uint8_t t1 = *bytes++;\n      const uint8_t t2 = *bytes++;\n\n      const uint32_t d1 = detail::decode_table_0[t1];\n      const uint32_t d2 = detail::decode_table_1[t2];\n\n      const uint32_t temp = d1 | d2;\n\n      if (temp >= detail::bad_char) {\n        throw std::runtime_error{\n            \"Invalid base64 encoded data - Invalid character\"};\n      }\n\n      const std::array<char, 4> tempBytes =\n          detail::bit_cast<std::array<char, 4>, uint32_t>(temp);\n      *currDecoding++ = tempBytes[detail::decidx0];\n      break;\n    }\n    default: {\n      throw std::runtime_error{\n          \"Invalid base64 encoded data - Invalid padding number\"};\n    }\n  }\n\n  return decoded;\n}\n\ntemplate <class OutputBuffer, class InputIterator>\ninline OutputBuffer decode_into(InputIterator begin, InputIterator end) {\n  typedef std::decay_t<decltype(*begin)> input_value_type;\n  static_assert(std::is_same_v<input_value_type, char> ||\n                std::is_same_v<input_value_type, signed char> ||\n                std::is_same_v<input_value_type, unsigned char> ||\n                std::is_same_v<input_value_type, std::byte>);\n  std::string_view data(reinterpret_cast<const char*>(&*begin), end - begin);\n  return decode_into<OutputBuffer>(data);\n}\n\ninline std::string from_base64(std::string_view data) {\n  return decode_into<std::string>(data);\n}\n\n}  // namespace base64\n\n#endif  // BASE64_HPP_\n"
  },
  {
    "path": "scripts/run-clang-format.sh",
    "content": "#!/usr/bin/env sh\nclang-format -style=Google -i include/*.hpp\nclang-format -style=Google -i test/*.cpp\n"
  },
  {
    "path": "scripts/run-s390x-emulation.sh",
    "content": "#!/usr/bin/env sh\n#\n#docker run --rm --privileged multiarch/qemu-user-static:register --reset\ndocker run -it multiarch/ubuntu-core:s390x-focal /bin/bash\napt-get update -q -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends make cmake g++ git\n#software-properties-common\ncd home\ngit clone https://github.com/tvercaut/base64.git\ncd base64\ngit checkout modpb64xover\ncmake -B ./build -DCMAKE_BUILD_TYPE=Debug .\ncmake --build ./build --config Debug\ncd build\nctest -C Debug --output-on-failure\n\n"
  },
  {
    "path": "test/base64_tests.cpp",
    "content": "// Test suite ported from https://github.com/matheusgomes28/base64pp\n#include <gtest/gtest.h>\n\n#include <array>\n#include <cstdint>\n#include <string>\n#include <vector>\n\n#include \"../include/base64.hpp\"\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesEmpty) {\n  std::string const expected{};\n  std::string const actual{base64::to_base64({})};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesThreeBytesZeros) {\n  std::array<std::uint8_t, 3> const input{0x00, 0x00, 0x00};\n  auto const expected{\"AAAA\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesThreeBytesRandom) {\n  std::array<std::uint8_t, 3> const input{0xFE, 0xE9, 0x72};\n  auto const expected{\"/uly\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesTwoBytes) {\n  std::array<std::uint8_t, 2> const input{0x00, 0x00};\n  auto const expected{\"AAA=\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesOneByte) {\n  std::array<std::uint8_t, 1> const input{0x00};\n  auto const expected{\"AA==\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesFourBytes) {\n  std::array<std::uint8_t, 4> const input{0x74, 0x68, 0x65, 0x20};\n  auto const expected{\"dGhlIA==\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesFiveBytes) {\n  std::array<std::uint8_t, 5> const input{0x20, 0x62, 0x72, 0x6f, 0x77};\n  auto const expected{\"IGJyb3c=\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesSixBytes) {\n  std::array<std::uint8_t, 6> const input{0x20, 0x6a, 0x75, 0x6d, 0x70, 0x73};\n  auto const expected{\"IGp1bXBz\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesBrownFox) {\n  std::array<std::uint8_t, 43> const input{\n      0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62,\n      0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75,\n      0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,\n      0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};\n\n  auto const expected{\n      \"dGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodesBrownFastFoxNullInMiddle) {\n  std::array<std::uint8_t, 45> const input{\n      0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x21, 0x20, 0x62,\n      0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75, 0x6d,\n      0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x00,\n      0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};\n\n  auto const expected{\n      \"dGhlIHF1aWNrISBicm93biBmb3gganVtcHMgb3ZlciB0aGUAIGxhenkgZG9n\"};\n  auto const actual{base64::encode_into<std::string>(begin(input), end(input))};\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeOneString) {\n  std::string const input{\"1\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeOneStringPadded) {\n  std::string const input{\"1===\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeOneCharRemaining) {\n  std::string const input{\"something\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeNonSize4Bigger) {\n  std::string const input{\"SomethingEntirelyDifferent\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::vector<std::uint8_t> const expected{0x4A, 0x89, 0x9E, 0xB6, 0x18,\n  // 0xA7, 0x80, 0x49, 0xED, 0x8A, 0xB7, 0xA5,\n  //     0xC8, 0x38, 0x9F, 0x7D, 0xEA, 0xDE, 0x9E};\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeNonBase64Short) {\n  std::string const input{\"a aa\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, FailDecodeNonBase64Longer) {\n  std::string const input{\"aaa`aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesMissingTwoPads0) {\n  std::string const input{\"12\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::vector<std::uint8_t> const expected{0xD7};\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesMissingTwoPads1) {\n  std::string const input = \"AA\";\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::vector<std::uint8_t> const expected{0x00};\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesMissingOnePad0) {\n  std::string const input = \"AAA\";\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::vector<std::uint8_t> const expected{0x00, 0x00};\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesMissingOnePad1) {\n  std::string const input{\"12a\"};\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::vector<std::uint8_t> const expected{0xD7, 0x66};\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesMissingIssueExample) {\n  std::string const input = \"eyJuYW1lIjoiSm9obiBEb2UifQ\";\n  ASSERT_THROW(base64::from_base64(input), std::runtime_error);\n  // For the record - expected decoding if relaxed checks\n  // std::string const expected_str = R\"({\"name\":\"John Doe\"})\";\n  // See https://github.com/matheusgomes28/base64pp/issues/84\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesEmptyString) {\n  std::string expected{};\n  auto const actual{base64::from_base64(\"\")};\n\n  ASSERT_EQ(expected, actual);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesZeroArray) {\n  std::string const input{\"AAAA\"};\n  std::vector<std::uint8_t> const expected{0x00, 0x00, 0x00};\n  auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};\n\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesZeroArrayTwice) {\n  std::string const input{\"AAAAAAAA\"};\n  std::vector<std::uint8_t> const expected{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};\n  auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};\n\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesZeroArrayOneByte) {\n  std::string const input{\"AA==\"};\n  std::vector<std::uint8_t> const expected{0x00};\n  auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};\n\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesZeroArrayTwoBytes) {\n  std::string const input{\"AAA=\"};\n  std::vector<std::uint8_t> const expected{0x00, 0x00};\n  auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};\n\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Decode, DecodesQuickFox) {\n  std::string const input{\n      \"VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==\"};\n  std::vector<std::uint8_t> const expected{\n      0x54, 0x68, 0x65, 0x20, 0x71, 0x75, 0x69, 0x63, 0x6b, 0x20, 0x62,\n      0x72, 0x6f, 0x77, 0x6e, 0x20, 0x66, 0x6f, 0x78, 0x20, 0x6a, 0x75,\n      0x6d, 0x70, 0x73, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x20, 0x74, 0x68,\n      0x65, 0x20, 0x6c, 0x61, 0x7a, 0x79, 0x20, 0x64, 0x6f, 0x67};\n  auto const actual{base64::decode_into<std::vector<std::uint8_t>>(input)};\n  ASSERT_EQ(actual, expected);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64RoundTripTests, AllPossibleBytes) {\n  std::vector<std::uint8_t> all_possible_bytes;\n  for (std::size_t i = 0; i <= 255; ++i) {\n    all_possible_bytes.push_back(static_cast<std::uint8_t>(i));\n  }\n\n  auto const encode_string = base64::encode_into<std::string>(\n      begin(all_possible_bytes), end(all_possible_bytes));\n  auto const decoded_bytes =\n      base64::decode_into<std::vector<std::uint8_t>>(encode_string);\n  ASSERT_EQ(all_possible_bytes, decoded_bytes);\n}\n\n// NOLINTNEXTLINE\nTEST(Base64RoundTripTests, ExhaustiveTests) {\n  std::vector<std::string> const base64_strings = {\n      \"YW55IGNhcm5hbCBwbGVhcw==\",\n      \"bGVnYWwgcGFzcw==\",\n      \"dGVzdCBzdHJpbmc=\",\n      \"bGVnYWwgcHJvdmlkZXI=\",\n      \"ZW5vdWdoIHRoZSBzYW1lIG9mIHRoZSBwbGFjZQ==\",\n      \"YW5vdGhlciB0aGUgc3RyYWlnaHQ=\",\n      \"d2FzIG1lIGFkZHJlc3MgcHJvdmlkZXI=\",\n      \"YWJvdXQgdGhlIG1hc3RlciBvZiB0aGUgZGFtYWdl\",\n      \"ZW50aXJlIHRoYXQgYnJvdWdodCBvZiB0aGUgbW9uZXk=\",\n      \"bGVnYWwgc2VjdXJpdHk=\",\n      \"YmFzaWMgZ29vZCBvZiB0aGUgcGFkIHN0cmluZw==\",\n      \"ZGVsZXRlIHN0cmluZyBvZiB0aGUgc3RyYWlnaHQ=\",\n      \"YnJvdWdodCBvZiB0aGUgcGFkIGZvbGRlciBvZiB0aGUgZGFtYWdl\",\n      \"aW50ZXJmYWNlIHN0cmluZw==\",\n      \"Y29uc29sZS1tZS1jb21wYW55\",\n      \"aW5mb3JtYXRpb24tbWVkaWE=\",\n      \"c3RhdHVzLXNlY3VyZQ==\",\n      \"Y3JlYXRlLWNvbXBhbnktc3RyaW5n\",\n      \"b3JkZXItbGVhZGVy\",\n      \"Y2F0YWxvZy1wcm9maWxl\",\n      \"dGVzdC1jb25zdWx0aW5n\",\n      \"YnJvdWdodC1sZWFkZXI=\",\n      \"YXNzaWduLW1lY2hhbmlzbQ==\",\n      \"bGVnYWwtY29udGFpbmVy\",\n      \"ZW1haWwtY29udGFpbmVy\",\n      \"aW5zdGFuY2UtY29udGFpbmVy\",\n      \"dGVzdC1jb21wYW55LWFuZC1wcm9maWxl\",\n      \"YmFzZTY0LWJhc2U=\",\n      \"cGFzc3dvcmQ=\",\n      \"Zm9vYmFy\",\n      \"Y29vbC1iYXNl\",\n      \"YmFzZTY0LXNlY3VyZQ==\",\n      \"aW50ZXJ2YWw=\",\n      \"dGhlLW1hc3Rlci1vZi10aGUtZGFtYWdl\",\n      \"c2FtZS1wbGFjZS1vZi10aGUtZGFtYWdl\",\n      \"aGFzaC1zb21ldGhpbmc=\"};\n\n  for (auto const& b64_string : base64_strings) {\n    auto const decoded = base64::from_base64(b64_string);\n\n    auto const encoded_round_trip = base64::to_base64(decoded);\n    ASSERT_EQ(encoded_round_trip, b64_string);\n  }\n}\n\n// NOLINTNEXTLINE\nTEST(Base64OverloadTests, EncodesString1) {\n  std::array<std::pair<std::string, std::string>, 11> const test_cases = {\n      {{\"\", \"\"},\n       {\"Hello, World!\", \"SGVsbG8sIFdvcmxkIQ==\"},\n       {\"abcdefghijklmnopqrstuvwxyz0123456789\\\\`!\\\"£$%^&*()_+\",\n        \"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XGAhIsKjJCVeJiooKV8r\"},\n       {\"Base64 encoding\", \"QmFzZTY0IGVuY29kaW5n\"},\n       {\"I love coding\", \"SSBsb3ZlIGNvZGluZw==\"},\n       {\"C++23 is awesome\", \"QysrMjMgaXMgYXdlc29tZQ==\"},\n       {\"This is a sample\", \"VGhpcyBpcyBhIHNhbXBsZQ==\"},\n       {\"Base64 is useful\", \"QmFzZTY0IGlzIHVzZWZ1bA==\"},\n       {\"Encode and decode\", \"RW5jb2RlIGFuZCBkZWNvZGU=\"},\n       {\"Data encryption\", \"RGF0YSBlbmNyeXB0aW9u\"},\n       {\"Th3 Quickk  Br0wn f0x\", \"VGgzIFF1aWNrayAgQnIwd24gZjB4\"}}};\n\n  for (auto const& [input, expected] : test_cases) {\n    auto const actual = base64::to_base64(input);\n    ASSERT_EQ(actual, expected);\n  }\n}\n\n// NOLINTNEXTLINE\nTEST(Base64RoundTripTests, TypeMixTests) {\n  const std::string strinput{\"Hello, World!\"};\n  const std::string stroutput{\"SGVsbG8sIFdvcmxkIQ==\"};\n\n  typedef std::vector<std::uint8_t> u8vec_type;\n  const u8vec_type uvecinput(strinput.begin(), strinput.end());\n  const u8vec_type uvecoutput(stroutput.begin(), stroutput.end());\n\n  typedef std::vector<std::int8_t> s8vec_type;\n  const s8vec_type svecinput(strinput.begin(), strinput.end());\n  const s8vec_type svecoutput(stroutput.begin(), stroutput.end());\n\n  // str -> str\n  {\n    auto tmp1 =\n        base64::encode_into<std::string>(strinput.begin(), strinput.end());\n    ASSERT_EQ(tmp1, stroutput);\n    auto tmp2 =\n        base64::decode_into<std::string>(stroutput.begin(), stroutput.end());\n    ASSERT_EQ(tmp2, strinput);\n    auto tmp3 = base64::encode_into<std::string>(strinput);\n    ASSERT_EQ(tmp3, stroutput);\n    auto tmp4 = base64::decode_into<std::string>(stroutput);\n    ASSERT_EQ(tmp4, strinput);\n    auto tmp5 = base64::to_base64(strinput);\n    ASSERT_EQ(tmp5, stroutput);\n    auto tmp6 = base64::from_base64(stroutput);\n    ASSERT_EQ(tmp6, strinput);\n  }\n\n  // str -> u8\n  {\n    auto tmp1 =\n        base64::encode_into<u8vec_type>(strinput.begin(), strinput.end());\n    ASSERT_EQ(tmp1, uvecoutput);\n    auto tmp2 =\n        base64::decode_into<u8vec_type>(stroutput.begin(), stroutput.end());\n    ASSERT_EQ(tmp2, uvecinput);\n    auto tmp3 = base64::encode_into<u8vec_type>(strinput);\n    ASSERT_EQ(tmp3, uvecoutput);\n    auto tmp4 = base64::decode_into<u8vec_type>(stroutput);\n    ASSERT_EQ(tmp4, uvecinput);\n  }\n\n  // str -> s8\n  {\n    auto tmp1 =\n        base64::encode_into<s8vec_type>(strinput.begin(), strinput.end());\n    ASSERT_EQ(tmp1, svecoutput);\n    auto tmp2 =\n        base64::decode_into<s8vec_type>(stroutput.begin(), stroutput.end());\n    ASSERT_EQ(tmp2, svecinput);\n    auto tmp3 = base64::encode_into<s8vec_type>(strinput);\n    ASSERT_EQ(tmp3, svecoutput);\n    auto tmp4 = base64::decode_into<s8vec_type>(stroutput);\n    ASSERT_EQ(tmp4, svecinput);\n  }\n\n  // u8 -> str\n  {\n    auto tmp1 =\n        base64::encode_into<std::string>(uvecinput.begin(), uvecinput.end());\n    ASSERT_EQ(tmp1, stroutput);\n    auto tmp2 =\n        base64::decode_into<std::string>(uvecoutput.begin(), uvecoutput.end());\n    ASSERT_EQ(tmp2, strinput);\n  }\n\n  // u8 -> u8\n  {\n    auto tmp1 =\n        base64::encode_into<u8vec_type>(uvecinput.begin(), uvecinput.end());\n    ASSERT_EQ(tmp1, uvecoutput);\n    auto tmp2 =\n        base64::decode_into<u8vec_type>(uvecoutput.begin(), uvecoutput.end());\n    ASSERT_EQ(tmp2, uvecinput);\n  }\n\n  // u8 -> s8\n  {\n    auto tmp1 =\n        base64::encode_into<s8vec_type>(uvecinput.begin(), uvecinput.end());\n    ASSERT_EQ(tmp1, svecoutput);\n    auto tmp2 =\n        base64::decode_into<s8vec_type>(uvecoutput.begin(), uvecoutput.end());\n    ASSERT_EQ(tmp2, svecinput);\n  }\n\n  // s8 -> str\n  {\n    auto tmp1 =\n        base64::encode_into<std::string>(svecinput.begin(), svecinput.end());\n    ASSERT_EQ(tmp1, stroutput);\n    auto tmp2 =\n        base64::decode_into<std::string>(svecoutput.begin(), svecoutput.end());\n    ASSERT_EQ(tmp2, strinput);\n  }\n\n  // s8 -> u8\n  {\n    auto tmp1 =\n        base64::encode_into<u8vec_type>(svecinput.begin(), svecinput.end());\n    ASSERT_EQ(tmp1, uvecoutput);\n    auto tmp2 =\n        base64::decode_into<u8vec_type>(svecoutput.begin(), svecoutput.end());\n    ASSERT_EQ(tmp2, uvecinput);\n  }\n\n  // s8 -> s8\n  {\n    auto tmp1 =\n        base64::encode_into<s8vec_type>(svecinput.begin(), svecinput.end());\n    ASSERT_EQ(tmp1, svecoutput);\n    auto tmp2 =\n        base64::decode_into<s8vec_type>(svecoutput.begin(), svecoutput.end());\n    ASSERT_EQ(tmp2, svecinput);\n  }\n}\n\nint main(int argc, char** argv) {\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "test/modp_b64_tests.cpp",
    "content": "// Test suite ported\n// https://github.com/client9/stringencoders/blob/master/test/modp_b64_test.c\n#include <gtest/gtest.h>\n\n#include <array>\n#include <cstdint>\n#include <string>\n#include <vector>\n\n#include \"../include/base64.hpp\"\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, Padding) {\n  // Test 1-6 bytes input and decode\n  {\n    /* 1 in, 4 out */\n    std::string const input{1};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(4, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n  {\n    /* 2 in, 4 out */\n    std::string const input{1, 1};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(4, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n  {\n    /* 3 in, 4 out */\n    std::string const input{1, 1, 1};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(4, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n  {\n    /* 4 in, 8 out */\n    std::string const input{1, 1, 1, 1};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(8, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n  {\n    /* 5 in, 8 out */\n    std::string const input{1, 1, 1, 1, 1};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(8, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n  {\n    /* 6 in, 8 out */\n    std::string const input{1, 1, 1, 1, 1, 6};\n    auto const encoded{base64::to_base64(input)};\n    ASSERT_EQ(8, encoded.size());\n    auto const decoded{base64::from_base64(encoded)};\n    ASSERT_EQ(input, decoded);\n  }\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, EncodeDecode) {\n  // Test all 17M 3 bytes inputs to encoder, decode\n  // and make sure it's equal.\n  for (int i = 0; i < 256; ++i) {\n    for (int j = 0; j < 256; ++j) {\n      for (int k = 0; k < 256; ++k) {\n        std::string const input{static_cast<char>(i), static_cast<char>(j),\n                                static_cast<char>(k)};\n        auto const encoded{base64::to_base64(input)};\n        ASSERT_EQ(4, encoded.size());\n        auto const decoded{base64::from_base64(encoded)};\n        ASSERT_EQ(input, decoded);\n      }\n    }\n  }\n}\n\n// NOLINTNEXTLINE\nTEST(Base64Encode, DecodeErrors) {\n  {\n    // test bad input -  all combinations\n    char goodchar = 'A';\n    char badchar = '~';\n    std::array<std::uint8_t, 4> decode;\n    for (int i = 1; i < 16; ++i) {\n      decode[0] = static_cast<char>(((i & 0x01) == 0) ? goodchar : badchar);\n      decode[1] = static_cast<char>(((i & 0x02) == 0) ? goodchar : badchar);\n      decode[2] = static_cast<char>(((i & 0x04) == 0) ? goodchar : badchar);\n      decode[3] = static_cast<char>(((i & 0x08) == 0) ? goodchar : badchar);\n\n      ASSERT_THROW(\n          base64::decode_into<std::string>(decode.begin(), decode.end()),\n          std::runtime_error);\n    }\n  }\n  {\n    // test just 1-4 padchars\n    for (int i = 1; i <= 4; ++i) {\n      std::vector<char> decode(i, '=');\n      ASSERT_THROW(\n          base64::decode_into<std::string>(decode.begin(), decode.end()),\n          std::runtime_error);\n    }\n  }\n  {\n    // Test good+3 pad chars (should be impossible)\n    std::string decode(\"A===\");\n    ASSERT_THROW(base64::decode_into<std::string>(decode.begin(), decode.end()),\n                 std::runtime_error);\n  }\n}\n\nint main(int argc, char** argv) {\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "test/roundtrip_test.cpp",
    "content": "#include <iostream>\n#include <string>\n#include <type_traits>\n#include <vector>\n\n#include \"../include/base64.hpp\"\n\nint runtests() {\n  const std::vector<int> lengths{5, 10, 100, 1024, 10000, 1000003};\n  int outcome = EXIT_SUCCESS;\n\n  std::cout << \"char is \"\n            << (std::is_signed<char>::value ? \"signed\" : \"unsigned\")\n            << std::endl;\n\n  std::cout << \"endianness is \"\n#if defined(__LITTLE_ENDIAN__)\n            << \"little endian\"\n#else\n            << \"big endian\"\n#endif\n            << std::endl;\n\n  for (auto& length : lengths) {\n    std::string original;\n    for (int i = 0; i < length; i++) {\n      original += static_cast<char>(std::rand());\n    }\n\n    auto encoded = base64::to_base64(original);\n    auto s = base64::from_base64(encoded);\n\n    if (s == original) {\n      std::cout << \"Test passed with length \" << length << std::endl;\n    } else {\n      std::cout << \"Test FAILED with length \" << length << std::endl;\n      outcome = EXIT_FAILURE;\n    }\n  }\n  return outcome;\n}\n\nint main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) {\n  try {\n    return runtests();\n  } catch (const std::exception& e) {\n    // standard exceptions\n    std::cout << \"Caught std::exception in main: \" << e.what() << std::endl;\n    return EXIT_FAILURE;\n  } catch (...) {\n    // everything else\n    std::cout << \"Caught unknown exception in main\" << std::endl;\n    return EXIT_FAILURE;\n  }\n}\n"
  }
]